2012-01-10 45 views
5

可能重复:
Why copy constructor is not called in this case?复制构造不调用

考虑下面的示例程序:

#include <iostream> 

using namespace std; 

class sample 
{ 
    private: 
     int x; 

    public: 
     sample(int a=0) : x(a) 
     { 
      cout << "default ctor invoked\n"; 
     } 

     sample(const sample& obj) 
     { 
      cout << "copy ctor invoked\n"; 
     } 

}; 

int main() 
{ 
    sample s2 = sample(20); //Line1 
    sample s3 = 20; //Line2 

    return 0; 
} 

Line1,第一sample类的构造函数被调用explicitly与参数20.然后我的预期要调用的复制构造函数来初始化s2。

在Line2中,首先使用参数20首先调用sample类的构造函数implicitly。这里我也希望调用copy构造函数来初始化s2。

在这两种情况下,复制构造函数都不会被调用?这是为什么发生?我相信,我对复制构造函数的调用有所了解。有人能纠正我在哪里出错吗?

+0

这是预期的 - 让我试试并找到一个好例子 – 2012-01-10 04:42:14

+0

在某些情况下,可以省略对复制构造函数的调用。 – 2012-01-10 04:45:12

+0

@ R.MartinhoFernandes:在某些情况下。但s2和s3必须以某种方式初始化。如何在没有调用copy ctor的情况下完成? – 2012-01-10 04:46:16

回答

8

这是预期的。它被称为copy elision

您的期望是正确的,但他们在C++(用于性能)中做了一个例外,它允许编译器将您的表达式视为一个实例的直接初始化,同时绕过复制构造函数。

+0

对于第一个例子是的,编译器可能决定做复制elision或不这样做。但是我认为在第二行中,'sample s3 = 20;',那么编译器*必须*只调用'int'构造函数。我想我问的是“在这两种情况下复制elision *可选*”? – 2012-01-10 04:51:09

+1

如果复制构造函数不可访问(即'private')或被删除,那么它们都不会工作。所以它不是直接初始化。 – 2012-01-10 04:59:06

+0

它们都需要复制初始化。两者相当于样本s(样本(20));'。你可以通过在拷贝ctor私有后编译来证明这一点。从不需要复制elision。它被编译器优化的标准*所允许*。它是否被删除取决于你的编译器。 – justin 2012-01-10 05:01:19

0

在第一行中它不会调用复制构造函数,因为您不复制对象。您正在将一个对象分配给其他对象。 C++提供执行浅拷贝的default =运算符。这是隐式调用的。为右手对象调用构造函数,为左手对象调用默认构造函数。之后,调用default =运算符。

对于第2行,它使用构造函数,它接受您定义的int参数。它实际上是转换器构造函数,因为它需要一个整数并创建类的对象。这就是为什么C++使用它作为转换器的构造函数,并且当你尝试给你的对象分配一个整数时,C++会明确地调用这个转换器的构造函数。

我希望这可以帮助你理解。

+0

Cemal:我认为你对Line1的解释不正确。正如我从给出答案和评论的其他人那样理解的,Line1和Line2都是复制初始化,但编译器通过阻止调用复制构造函数来优化它以直接初始化。 – 2012-01-10 07:31:58

+1

是的你有权利。一般来说,当你使用=运算符时,它使用拷贝构造函数,但是我没有根据提问者的要求来实现。正如你所说,我没有考虑编译器优化,直接思考。感谢您的警告 – 2012-01-10 07:34:45