没有调用复制构造函数

时间:2011-08-24 10:04:52

标签: c++

考虑一下:

#include <iostream>

struct A{
   A(){
       std::cout << "Create empty A" << std::endl;
   }

   A(const A& a){
       // Why is this never called??
       std::cout << "Never called" << std::endl;
   }
};

A genA() {
   A a;
   return a;
}

int main(int argc, const char *argv[])
{
   A a(genA()); // Expected to call copy constructor
   return 0;
}

为什么没有调用复制构造函数?

如果我想确保每次复制A时屏幕上都会打印“从不通话”,我该怎么办。

3 个答案:

答案 0 :(得分:7)

这称为 Return value optimization 编译器可以优化您的代码,使其直接在复制对象的位置进行压缩。因此没有理由使用复制构造函数。

注意:标准明确允许它这样做。

答案 1 :(得分:2)

可以强制编译器避免RVO的一种方法是不按值返回 - 例如

#include <iostream>
#include <memory>

struct A{
   A() {
       std::cout << "Create empty A" << std::endl;
   }

   A(const A& a) {
       // This will be called now
       std::cout << "Never called" << std::endl;
   }
};

std::auto_ptr<A> genA() {
   return std::auto_ptr<A>(new A);
}

int main(int argc, const char *argv[])
{
   A a(*(genA().get())); // this will trigger the copy-ctor
   return 0;
}

虽然这是一个可怕的黑客。我会问你为什么要这样做?如果你希望在构造函数中加入一些副作用,请你不要这么想。

答案 2 :(得分:1)

复制构造函数调用可以省略(即使它们包含副作用),标准允许([12.2])。

修改

我建议您不要尝试在现实代码中对抗它。

如果你只是想看一些示例/ turorial代码中执行的copy ctor,那么通常有助于不进行优化编译。有些编译器甚至有开关可以帮助避免这种情况。对于GCC,它应该是-fno-elide-constructors