繁体   English   中英

为什么要使用复制构造函数C ++

[英]Why to use copy constructor C++

据我所知,当我们分配一个对象是另一个默认副本构造函数将被调用。

class class1 obj1;
class class2 obj2;
obj1(obj2); //default copy constructor will be called by compiler 

那么,什么时候应该显式地编写副本构造函数?

在您的情况下,将调用复制分配运算符,而不是复制构造函数。 要调用复制构造函数,您必须执行例如

class1 obj1;
class1 obj2 = obj1;  // Invokes the copy-constructor in obj2

当编写复制构造函数(或复制分配运算符或析构函数)时,一个好主意可以通过阅读3规则来了解。 简而言之,如果您具有析构函数,复制构造函数或复制赋值运算符中的任何一个,那么您可能应该全部拥有。


此外,尽管如果您不提供自己的编译器,编译器会自动为您生成copy-constructor和copy-assignment运算符,但您必须记住,这些自动生成的函数只会进行浅表复制。 如果您在对象中分配了例如指向内存的指针,则自动生成的函数将仅复制实际指针,而不复制其指向的指针。 这意味着在复制后,您将拥有两个都指向同一内存的对象。 如果delete析构函数中的指针,并且其中一个对象被破坏,则另一个对象仍将具有其指针,但是现在它指向已删除的内存。

如果不编写三个或五个类别中的任何一个,则无需编写任何一个,便会得到默认的复制构造函数:析构函数,复制或移动赋值或构造函数。

有时,这样做是正确的。 例如,如果您只需要浅表副本,或者该成员的相应函数具有正确的用途,例如智能指针。

如果对象在分配之前存在,那么它不涉及构造,而是分配运算符,签名为:

T& operator=( T const & ); // from l-value ref
T& operator=( T && ); // from r-value ref, since c++11

一种常见的策略是将赋值运算符编写为惯用语“复制和交换”:

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;
}

在某些情况下,您会发现复制对象的方式并不简单。 如果您考虑上课:

class Car {
 string BrandName;
 int NumberOfPassenger;
}

显然,当您要复制两个对象时,您只想逐个成员地复制它们。 这里没有什么特别的事情,因此defaut复制构造函数可以正常工作。

但是,假设该类是:

class Car {
 string BrandName;
 int NumberOfPassenger;
 Mechanics EngineeringStuff;
}

在这里,力学是参考类型。 复制构造函数将要做的只是将引用复制到新对象,因此car1和car2这两个car将共享相同的EngineeringStuff。 但是更自然的行为是执行复制时手动分配新的Mechanics对象,因此汽车不会共享相同的车轮,马达等。

更一般而言,通常是在必须处理引用类型或某种类型的业务逻辑时,才需要显式地编写副本构造函数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM