0

以下代码仅打印A::A(),但不打印A::A(const A&)or 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()under的内联。g++

4

2 回答 2

10

这称为“返回值优化”。在这种情况下,允许编译器删除副本。

于 2012-10-14T23:47:52.977 回答
3

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

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

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

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

于 2012-10-15T01:06:37.743 回答