jer*_*son 47 c++ contains composition default-copy-constructor
我知道如果你没有自己实现,编译器有时会提供一个默认的复制构造函数.我很困惑这个构造函数到底是做什么的.如果我有一个包含其他对象的类,其中没有一个具有声明的复制构造函数,那么行为是什么?例如,像这样的类:
class Foo {
Bar bar;
};
class Bar {
int i;
Baz baz;
};
class Baz {
int j;
};
Run Code Online (Sandbox Code Playgroud)
现在,如果我这样做:
Foo f1;
Foo f2(f1);
Run Code Online (Sandbox Code Playgroud)
默认的复制构造函数会做什么?将编译器生成的复制构造函数Foo调用编译器生成的构造函数Bar进行复制bar,然后调用编译器生成的复制构造函数Baz吗?
Mar*_*ork 68
Foo f1;
Foo f2(f1);
Run Code Online (Sandbox Code Playgroud)
是的,这将按照您的预期执行:
调用f2复制构造函数Foo :: Foo(Foo const&).
此副本构造其基类,然后构造每个成员(递归)
如果你定义一个这样的类:
class X: public Y
{
private:
int m_a;
char* m_b;
Z m_c;
};
Run Code Online (Sandbox Code Playgroud)
您的编译器将定义以下方法.
实际上有两个默认构造函数.
一个用于zero-initialization而另一个用于value-initialization.使用取决于您是否()在初始化期间使用.
// Zero-Initialization compiler generated constructor
X::X()
:Y() // Calls the base constructor
// If this is compiler generated use
// the `Zero-Initialization version'
,m_a(0) // Default construction of basic PODS zeros them
,m_b(0) //
m_c() // Calls the default constructor of Z
// If this is compiler generated use
// the `Zero-Initialization version'
{
}
// Value-Initialization compiler generated constructor
X::X()
:Y() // Calls the base constructor
// If this is compiler generated use
// the `Value-Initialization version'
//,m_a() // Default construction of basic PODS does nothing
//,m_b() // The values are un-initialized.
m_c() // Calls the default constructor of Z
// If this is compiler generated use
// the `Value-Initialization version'
{
}
Run Code Online (Sandbox Code Playgroud)
注意:如果基类或任何成员没有有效的可见默认构造函数,则无法生成默认构造函数.除非您的代码尝试使用默认构造函数(然后只是编译时错误),否则这不是错误.
X::X(X const& copy)
:Y(copy) // Calls the base copy constructor
,m_a(copy.m_a) // Calls each members copy constructor
,m_b(copy.m_b)
,m_c(copy.m_c)
{}
Run Code Online (Sandbox Code Playgroud)
注意:如果基类或任何成员没有有效的可见复制构造函数,则无法生成复制构造函数.除非您的代码尝试使用复制构造函数(然后只编译时错误),否则这不是错误.
X& operator=(X const& copy)
{
Y::operator=(copy); // Calls the base assignment operator
m_a = copy.m_a; // Calls each members assignment operator
m_b = copy.m_b;
m_c = copy.m_c;
return *this;
}
Run Code Online (Sandbox Code Playgroud)
注意:如果基类或任何成员没有有效的可行赋值运算符,则无法生成赋值运算符.除非您的代码尝试使用赋值运算符(然后只是编译时错误),否则这不是错误.
X::~X()
{
// First runs the destructor code
}
// This is psudo code.
// But the equiv of this code happens in every destructor
m_c.~Z(); // Calls the destructor for each member
// m_b // PODs and pointers destructors do nothing
// m_a
~Y(); // Call the base class destructor
Run Code Online (Sandbox Code Playgroud)
查看代码,生成以下复制构造函数:
Foo::Foo(Foo const& copy)
:bar(copy.bar)
{}
Bar::Bar(Bar const& copy)
:i(copy.i)
,baz(copy.baz)
{}
Baz::Baz(Baz const& copy)
:j(copy.j)
{}
Run Code Online (Sandbox Code Playgroud)
sbi*_*sbi 11
除非您自己声明(注意:未定义),否则编译器会提供复制构造函数.编译器生成的复制构造函数只是调用类的每个成员(以及每个基类)的复制构造函数.
赋值运算符和析构函数BTW也是如此.但是默认构造函数不同:只有在您不自己声明任何其他构造函数时,才由编译器提供.