【问题标题】:copy constructor c++ on temporary objects在临时对象上复制构造函数 C++
【发布时间】:2013-05-26 07:17:36
【问题描述】:
#include <iostream>
using namespace std;

class A
{
    int x;

public:
    A(int c) : x(c) {}
    A(const A& a) { x = a.x; cout << "copy constructor called" << endl;}
};

class B
{
    A a;

public:
    B(int c) : a(c) {}
    B(const B& b) : a(b.a) { }
    A get_A() { return a;}
};

int main()
{
    B b(10);
    A a1 = b.get_A();

}

在上面的代码中,我预计“调用复制构造函数”消息会弹出两次,因为首先,b.get_A() 将创建一个调用复制构造函数 (1) 的临时对象,其次,它将复制其引用到 a1 的复制构造函数 (2) ,从而显示两条消息。

但是,代码实际上会生成一条“称为复制构造函数”的消息。为什么?

【问题讨论】:

标签: c++ constructor copy-constructor


【解决方案1】:

C++ 标准允许在某些情况下使用copy constructor to be elided。通常,这意味着对象是否将从临时变量复制构造。它可以就地建造。

在这种情况下,get_A(); 已将副本返回到临时文件中。然后将a1 分配给该临时变量。允许编译器省略多余的副本并在原地构造a1,返回值为get_A()

即使复制构造函数有副作用,也可能发生这种优化。

复制省略是唯一允许的可以改变可观察到的副作用的优化形式。由于某些编译器不会在允许的所有情况下都执行复制省略,因此依赖于复制/移动构造函数和析构函数的副作用的程序是不可移植的。

【讨论】:

    【解决方案2】:

    在 C++11 中,代码可能会调用移动构造函数来移动对象而不是复制它,或者在 C++03 和 C++11 中,NRVO 形式的编译器优化可能适用 copy elision 删除副本。

    请注意,后者(复制省略)取决于编译器的能力,不能保证,而前者(移动语义)在 C++11 中是有保证的。

    【讨论】:

    • 我使用了visual studio 2012(支持c++11)并且没有调用移动构造函数:(
    • A(const A&& a) { x = a.x; cout
    • @LeeJaeBeom:通常,所有优秀的编译器都会应用复制省略优化,但请注意编译器不必应用此优化。不能保证。在 gcc 上,您可以使用 -fno-elide-constructors 设置通过显式禁用复制省略来检查行为。
    • @AlokSave;谢谢,我现在可以看到临时的constructorsdestructors
    猜你喜欢
    • 2011-01-20
    • 1970-01-01
    • 2015-12-05
    • 2010-12-22
    • 2016-10-10
    • 2021-07-07
    • 1970-01-01
    • 2013-08-29
    • 1970-01-01
    相关资源
    最近更新 更多