据我所知,当我们分配一个对象时,将会调用另一个默认的复制构造函数。
class class1 obj1;
class class2 obj2;
obj1(obj2); //default copy constructor will be called by compiler
那么,我什么时候应该明确写出复制构造函数?
答案 0 :(得分:8)
在您的情况下,将调用复制赋值运算符,而不是复制构造函数。要调用复制构造函数,你可以这样做。
class1 obj1;
class1 obj2 = obj1; // Invokes the copy-constructor in obj2
通过阅读the rule of three,您可以看到何时编写复制构造函数(或复制赋值运算符或析构函数)。简而言之,如果您有任何的析构函数,复制构造函数或复制赋值运算符,那么您可能应该所有。
此外,虽然编译器会为您自动生成复制构造函数和复制赋值运算符,但如果您不提供自己的,则必须记住这些自动生成的函数只会执行浅复制。如果您有例如指向您在对象中分配的内存的指针,自动生成的函数将只复制实际指针,而不是它指向的内容。这意味着在复制后,您有两个指向同一内存的对象。如果delete
析构函数中的指针,并且其中一个对象被破坏,则另一个对象仍将具有其指针,但现在它将指向已删除的内存。
答案 1 :(得分:0)
如果您没有将three or five添加到您的类中,您将获得一个默认的复制构造函数:析构函数,复制或移动赋值或构造函数。< / p>
有时这是正确的事情。例如,如果您只需要浅层副本,或者成员的相应功能是正确的,例如智能指针。
答案 2 :(得分:-1)
如果在赋值之前存在一个对象,那么它不涉及构造,但是赋值运算符,签名是:
T& operator=( T const & ); // from l-value ref
T& operator=( T && ); // from r-value ref, since c++11
一种常见的策略是将赋值运算符编写为成语&#34;复制和交换&#34; :
T& operator=( T const & o ) {
T val( o ); // you need to write the copy ctor
swap(*this,o); // you need to write the swap
return *this;
}
T& operator=( T && o ) {
T val( std::move(o) ); // you need to write the move ctor
swap(*this,o); // you need to write the swap
return *this;
}
该策略的c ++ 11版本
T& operator=( T o ) noexcept { // copy done before the operator that can be noexcept ( swap have to too)
swap(*this,o); // you need to write the swap
return *this;
}
答案 3 :(得分:-1)
在某些情况下,您会发现应该复制对象的方式并非易事。 如果你考虑上课:
class Car {
string BrandName;
int NumberOfPassenger;
}
然后很明显,当你要复制两个对象时,你只需要逐个成员复制它们。这里没什么特别的,所以defaut拷贝构造函数可以正常工作。
但想象一下这个课程是:
class Car {
string BrandName;
int NumberOfPassenger;
Mechanics EngineeringStuff;
}
这里的力学是一种参考类型。复制构造函数将做的只是将引用复制到新对象,因此两个car - car1和car2 - 将共享相同的EngineeringStuff。但更自然的行为是在执行复制时手动分配新的力学对象,因此汽车不会共享相同的车轮,电机等......
更一般地说,通常在您必须处理引用类型或某种业务逻辑时,您需要明确地编写复制构造函数。