2017-10-16 133 views
2

有些东西我无法理解。看看这样的主:C++了解复制构造函数

class C { 
public: 
    C() { cout << "C0 "; } 
    C(const C&) { cout << "Cc"; } 
}; 

class D { 
public: 
    C c; 
    D() { cout << "D0 "; } 
    D(const D&) { cout << "Dd"; } 
}; 

int main() { 

    D x; cout << endl; 
    D y(x); cout << endl; 
    return 0; 

} 

//output is: 
C0 D0 
C0 Dd 

我同意的事实,D xC0 D0作为输出,因为d类存在于C默认构造函数的调用,然后创建对象D

D y(x)就像D y = x其中(像以前一样)C被创建(所以输出C0)和复制构造函数被调用。为什么不出现Cc?如果你考虑这个代码:

class C { 
public: 
    C() { cout << "C0 "; } 
    C(const C&) { cout << "Cc"; } 
}; 

class D { 
public: 
    C c; 
    D() { cout << "D0 "; } 
}; 

int main() { 

    D x; cout << endl; 
    D y(x); cout << endl; 
    return 0; 

} 

//output is: 
C0 D0 
Cc 

为什么现在输出是Cc

的代码是,除了一个事实,即没有对D的拷贝构造函数话说D y(x)就像D y = x我期望像以前一样创建(调用默认的构造函数,以便输出C0)是c的定义相同然后没有文字,因为D(const D&)而不是定义。

也许我误解了复制构造函数。他们在这种情况下叫什么名字?

+0

你在找什么是[“隐含声明的拷贝构造函数”](http://en.cppreference.com/w/cpp/language/copy_constructor#Implicitly-declared_copy_constructor) –

+0

@DrewDormann正是那个;) –

回答

3

而且D y(x)就像D y = x

它不喜欢它,正是它。后者只是第一个语法糖。

其中(像以前一样)C创建(所以输出C0)和拷贝构造函数被调用

没有,C拷贝构造函数是不是在这种情况下调用。您没有定义您的D拷贝构造函数来调用C拷贝构造函数,所以c成员是默认构造的,这就是您看到C0的原因,但由于您实际上没有拷贝c,所以您看不到Cc

您所期待的D拷贝构造函数来自动通话D的成员的拷贝构造函数,但是这根本就不是这样。你必须明确地定义这种行为自己,如:

D(const D &src) : c(src.c) { } 

为什么不Cc出现?

因为您的C拷贝构造函数根本没有在您的D y(x)示例中调用。

+0

完美清晰的答案,我现在明白了。 –

+0

一个无意义的问题。我已经仔细阅读了你写的内容,并且我自己意识到了答案(并且对视觉工作室的测试证实了它)。再次感谢 –

6

在第一种情况下,您的D Copy构造函数需要显式调用C复制构造函数。

D(const D &d) : c(d.c) 
{ cout << "Dd"; } 

在第二种情况下,由于您没有定义D copy-ctor,编译器会为您生成一个。

为了使这更清晰,增加了额外的int于C和D.

static int counter; 
class C { 
public: 
    int index; 
    C() { index = ++counter; cout << "C0 "; } 
    C(const C&) { index = c.counter; cout << "Cc"; } 
}; 

class D { 
public: 
    int dcounter; 
    C c; 
    D() { dcounter = ++counter; cout << "D0 "; } 
    D(const D&) : dcounter(D.dcounter) 
{ cout << "Dd"; } 
}; 

现在,调试步骤直通,或添加更多printfs输出()。 当您执行D y(x)时,您会看到y中的成员c不是从任何东西中拷贝的 - 只是构造而已。

+0

你是正确的。 Sombody编辑了我的答案,并将其放在operator =()的部分。我现在删除了。 – joeking

3

当你定义一个自定义的拷贝构造函数时,它会做你告诉它的事情;你不会告诉它复制c成员,所以它不会,因此C0。事实上,如果你的价值在于c,你会发现它甚至在新复制的成员中都没有。

如果您没有自定义副本构造函数,则被调用的默认副本构造函数会为其复制的成员调用复制构造函数。在这种情况下,您会在复制的实例中看到最终值。

+0

谢谢。所以在第一种情况下,我的D(const D&),因为我没有告诉他做一个副本,它没有复制项目。正确?我以为复制是在默认情况下完成的,我没有写它 –

+1

这是正确的,你没有告诉'D'复制构造函数复制'c',所以它没有。您必须在成员初始化列表中自己调用成员拷贝构造函数。 –