为什么返回不复制对象?

时间:2012-10-14 23:45:10

标签: c++ return copy-constructor

以下代码仅打印A::A(),但不打印A::A(const A&)operator=。为什么呢?

struct A
{
  A()               { cout << "A::A()" << endl; }
  A(const A& value) { cout << "A::A(const A&)" << endl; }

  A& operator=(const A& newValut)
  {
    cout << "A::operator=" << endl; 
    return *this;
  }
};

A foo()
{
  A a;      //Ok, there we have to create local object by calling A::A().
  return a; //And there we need to copy it, otherwise it will be destroyed
            //because it's local object. But we don't.
}

int main()
{
    A aa = foo(); //Also there we need to put result to the aa
                  //by calling A::A(const A&), but we don't.
}

所以这段代码必须打印

A::A()
A::A(const A&)
A::A(const A&)

但事实并非如此。为什么呢?

我建议foo()下的g++没有优化内容。

2 个答案:

答案 0 :(得分:10)

这称为"Return Value Optimization"。在这种情况下,允许编译器忽略副本。

答案 1 :(得分:3)

这是在C ++中返回复杂类型的方式:返回对象的位置实际上是在调用函数之前由调用者提供的,并且指向这个尚未初始化的对象的指针作为隐藏参数传递给功能。该函数使用此内存位置从返回的表达式构造返回的对象。

因此,当返回的对象要直接初始化程序A aa = foo();中的新对象时,它不需要将返回的值复制到堆栈上的对象。它要求函数直接在此位置创建对象。因此,只需要对复制构造函数进行一次调用。 (事实上​​,如果您有2次调用复制构造函数,则C ++编译器将不兼容)。

现在,最重要的是,允许编译器在称为“返回值优化”或RVO的优化中优化此调用。怎么可能?如果查看代码,可以看到可以在返回值的建议位置直接在foo()中定义本地“a”变量,因此不必再次复制它。这是一个重要的特性,因为复制构造函数可能很复杂且运行缓慢,因此这可以在实现时显着提高性能(并且我知道的每个编译器都实现了此功能)。

因此,在您的情况下,根据编译器的不同,您可能会对复制构造函数进行1或0调用,并且您的编译器仍然符合要求。