简体   繁体   English

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

[英]Why to use copy constructor C++

As i know, when we assign one object is another default copy constructor will be called. 据我所知,当我们分配一个对象是另一个默认副本构造函数将被调用。

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

So, when should I write explicitly the copy constructor? 那么,什么时候应该显式地编写副本构造函数?

In your case the copy-assignment operator will be called, not the copy-constructor. 在您的情况下,将调用复制分配运算符,而不是复制构造函数。 To call the copy-constructor you would have do to eg 要调用复制构造函数,您必须执行例如

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

A good idea when to write a copy-constructor (or a copy-assignment operator, or a destructor) you can see by reading about the rule of three . 当编写复制构造函数(或复制分配运算符或析构函数)时,一个好主意可以通过阅读3规则来了解。 In short, if you have any of a destructor, copy-constructor or copy-assignment operator, then you should probably have all of them. 简而言之,如果您具有析构函数,复制构造函数或复制赋值运算符中的任何一个,那么您可能应该全部拥有。


Also, while the compiler will auto-generate copy-constructor and copy-assignment operator for you if you do not provide your own, you have to remember that those auto-generated function will only do a shallow copy. 此外,尽管如果您不提供自己的编译器,编译器会自动为您生成copy-constructor和copy-assignment运算符,但您必须记住,这些自动生成的函数只会进行浅表复制。 If you have eg pointers to memory you allocate in the object, the auto-generated functions will only copy the actual pointer, and not what it points to. 如果您在对象中分配了例如指向内存的指针,则自动生成的函数将仅复制实际指针,而不复制其指向的指针。 This means that after a copy you have two objects both pointing to the same memory. 这意味着在复制后,您将拥有两个都指向同一内存的对象。 If you delete the pointer in the destructor, and one of the objects are destructed, the other object will still have its pointer, but it will now point to deleted memory. 如果delete析构函数中的指针,并且其中一个对象被破坏,则另一个对象仍将具有其指针,但是现在它指向已删除的内存。

You will get a default copy constructor when you don't write one, provided you don't add any of the three or five to your class : destructor, copy or move assignment or constructor. 如果不编写三个或五个类别中的任何一个,则无需编写任何一个,便会得到默认的复制构造函数:析构函数,复制或移动赋值或构造函数。

Sometimes this does the right thing. 有时,这样做是正确的。 For example, if you just need a shallow copy, or if the member's corresponding functions fo the right thing, for example smart pointers. 例如,如果您只需要浅表副本,或者该成员的相应函数具有正确的用途,例如智能指针。

If an object exist prior to the assign, then it does not involve a construction but the assignment operator, signatures are: 如果对象在分配之前存在,那么它不涉及构造,而是分配运算符,签名为:

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

A frequent strategy is to write the assignment operator as the idiom "copy and swap" : 一种常见的策略是将赋值运算符编写为惯用语“复制和交换”:

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

The c++11 version of that strategy 该策略的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;
}

In some cases you will find that the way your objects should be copied is not trivial. 在某些情况下,您会发现复制对象的方式并不简单。 If you consider the class : 如果您考虑上课:

class Car {
 string BrandName;
 int NumberOfPassenger;
}

Then it is clear that when you'll be copying two objects, you'll simply want to copy them member by member. 显然,当您要复制两个对象时,您只想逐个成员地复制它们。 There's nothing special to do here so the defaut copy constructor will work just fine. 这里没有什么特别的事情,因此defaut复制构造函数可以正常工作。

But imagine that the class is instead : 但是,假设该类是:

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

Here Mechanics is a reference type. 在这里,力学是参考类型。 What the copy constructor will do is simply copying the reference to the new object, so both cars - car1 and car2 - will share the same EngineeringStuff. 复制构造函数将要做的只是将引用复制到新对象,因此car1和car2这两个car将共享相同的EngineeringStuff。 But a more natural behaviour would be to allocate manually a new Mechanics object when performing the copy, so the cars don't share the same wheels, motors etc... 但是更自然的行为是执行复制时手动分配新的Mechanics对象,因此汽车不会共享相同的车轮,马达等。

More generally, it's usually when you have to deal with reference types or certain kind of business logic that you will need to explicitly write your copy constructor. 更一般而言,通常是在必须处理引用类型或某种类型的业务逻辑时,才需要显式地编写副本构造函数。

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

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