考虑一下:
#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时屏幕上都会打印“从不通话”,我该怎么办。
答案 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
。