我对C ++中的copy-constructor感到困惑

时间:2012-03-13 09:07:57

标签: c++ constructor copy-constructor

  

可能重复:
  Why copy constructor is not called in this case?

在下面的代码中,我构造了三个变量a1,a2和a3。

C ++ Primer p.476中有一个例子:

string empty_copy = string();//copy-initialization

有没有人可以帮我解释

1)为什么a1和a2不是由复制构造函数和

构造的

2)我的代码中的初始化a2与书中的empty_copy有什么区别?

非常感谢!

#include<iostream>
using namespace std;
class A{
public:
    A(){}
    A(int v){}
    A(const A&x){
        cout<<"copy constructor"<<endl;
    }
};
A generateA(){
    return A(0);
}
int main(){
        cout<<"First:"<<endl;
        A a1=generateA();

        cout<<"Second:"<<endl;
        A a2=A(0);

        cout<<"Third:"<<endl;
        A a3=a1;
    return 0;
}

输出是(在Win7中的Visual Studio 2010和Ubuntu10.10中的g ++):

First:
Second:
Third:
copy constructor

3 个答案:

答案 0 :(得分:6)

由于 Return value optimization ,这是复制省略 允许编译器通过应用此类优化来优化副本的生成。

A a1=generateA(); 
A a2=A(0); 

在上述两种情况下,编译器都可以消除创建临时对象的过程,该对象是为保存返回值而创建的。

A a3=a1;

涉及用于构造a1的已存在的命名对象a3,这涉及编译器必须进行的复制构造函数调用,并且无法进行优化。

编辑:在评论中回答问题。

您可以通过在编译期间使用以下选项告诉编译器不应用此优化:

GCC:

-fno-elide-constructors

对于 MVSC:

/Od

答案 1 :(得分:1)

  1. 复制构造函数不用于a1a2,因为在这两种情况下都要传递int,因此编译器正在使用A(int)你定义的构造函数。

  2. 你和本书中的例子之间的区别在于,本书是在堆栈上创建一个实例(string()),因此得到一个空副本,而在你的情况下,你正在使用现有实例(a1)。两者都使用复制构造函数进行初始化。

答案 2 :(得分:1)

初始化a1时,您有一个整数参数(在工厂函数中给出)。对于a2,您还传递一个整数。对于a3,你说a3 = a1。这被解释为a3(a1),因为你定义了一个拷贝构造函数,因此它被调用。