简体   繁体   English

我应该何时定义自己的副本ctor和赋值运算符

[英]When should I define my own copy ctor and assignment operator

I am reading effective C++ in Item 5, it mentioned two cases in which I must define the copy assignment operator myself. 我正在阅读第5项中有效的C ++,它提到了两种我必须自己定义复制赋值运算符的情况。 The case is a class which contain const and reference members. 该案例是一个包含const和引用成员的类。

I am writing to ask what's the general rule or case in which I must define my own copy constructor and assignment operator? 我写信是为了询问我必须定义自己的复制构造函数和赋值运算符的一般规则或情况是什么?

I would also like to know when I must define my own constructor and destructor. 我还想知道何时必须定义自己的构造函数和析构函数。

Thanks so much! 非常感谢!

You must create your own copy constructor and assignment operator (and usually default constructor too) when: 在以下情况下,您必须创建自己的复制构造函数和赋值运算符(通常也是默认构造函数):

  • You want your object to be copied or assigned, or put into a standard container such as vector 您希望复制或分配对象,或将其放入标准容器(如vector
  • The default copy constructor and assignment operator will not do the Right Thing. 默认的复制构造函数和赋值运算符不会执行正确的操作。

Consider the following code: 请考虑以下代码:

class A; // defined elsewhere
class B {
private:
    A *my_very_own_a;
};

If you let the automatic copy constructor copy a B , it will copy the A * pointer value across, so that the copy points to the same A instance as the original. 如果让自动复制构造函数复制B ,它将复制A *指针值,以便复制指向与原始实例相同的A实例。 But part of the design of this class is that each B has its own A , so the automatic copy constructor has broken that contract. 但是这个类的部分设计是每个B都有自己的A ,所以自动复制构造函数已经打破了这个契约。 So you need to write your own copy constructor which will create a new A for the new B to point to. 因此,您需要编写自己的复制构造函数,这将为要指向的新B创建新的A

However, consider this case: 但是,考虑这种情况:

class A; // defined elsewhere
class B {
private:
    A *shared_reference_to_a;
};

Here each B contains a pointer to an A , but the class contract doesn't demand a unique A for each B . 这里每个B包含一个指向A的指针,但是类合约不要求每个B都有唯一的A So the automatic copy constructor might well do the Right Thing here. 所以自动复制构造函数可能会在这里做正确的事情。

Note that both examples are the same code , but with different design intent . 请注意,这两个示例都是相同的代码 ,但具有不同的设计意图

An example of the first situation might be B == dialog box, A == button. 第一种情况的示例可能是B ==对话框, A ==按钮。 If you create a copy of a dialog box, it probably needs a copy of all the contents too. 如果创建对话框的副本,则可能还需要所有内容的副本。

An example of the second might be B == dialog box, A == reference to window manager. 第二个例子可能是B ==对话框, A ==对窗口管理器的引用。 If you copy a dialog box, the copy probably exists in the same window manager as the original. 如果复制对话框,则副本可能与原始窗口管理器位于同一窗口管理器中。

The default copy constructor often causes two objects to "point to" a common piece of memory. 默认的复制构造函数通常会导致两个对象“指向”一个共同的内存。 This is because all the default copy constructor does is memberwise assignment. 这是因为所有默认的复制构造函数都是成员分配。 So if you have a pointer member, this can get you into trouble 因此,如果你有一个指针成员,这可能会让你陷入困境

    CClass::CClass(const CClass& src)
    {
       // these two point to the same place in memory now
       // you really aught to allocate new memory
       m_ptr = src.m_ptr;

       // not a big deal for members that aren't "pointing" elsewhere
       // this copy works great
       m_int = src.m_int;
    }

You essentially don't want to end up in a situation where two instances are "pointing to" the same place in memory. 您基本上不希望最终处于两个实例“指向”内存中相同位置的情况。 This can happen when you have pointers as members which point to dynamically allocated memory. 当指针作为成员指向动态分配的内存时,就会发生这种情况。 This can also happen with references, both referring to something outside the class itself. 引用也可能发生这种情况,都引用了类本身之外的东西。 This can happen with file handles, where you may need to duplicate/reopen a new file. 文件句柄可能会发生这种情况,您可能需要复制/重新打开新文件。

In fact, the latter case is probably the easiest to conceptualize. 事实上,后一种情况可能是最容易概念化的。 Pretend your 2 C++ objects both had a log file. 假装你的2个C ++对象都有一个日志文件。 Without a correctly functioning copy constructor, they could both be logging to the same file. 如果没有正确运行的复制构造函数,它们都可以记录到同一个文件。 What happens if in the classes destructor, the file is closed out? 如果在类析构函数中,文件被关闭会发生什么? Well then the 2nd C++ object will have it's log file closed out from underneath him. 那么第二个C ++对象将从它下面关闭它的日志文件。 One solution would be to create a copy-constructor that creates a new file for the newly constructed instance. 一种解决方案是创建一个复制构造函数,为新构造的实例创建一个新文件。 So when the 1st C++ object goes away, it doesn't take the 2nd C++ object's log file with it. 因此,当第一个C ++对象消失时,它不会使用第二个C ++对象的日志文件。 They have 2 independent log files, they can't interfere with each other. 它们有2个独立的日志文件,它们不能相互干扰。

This example can be extended to dynamic memory. 此示例可以扩展到动态内存。 Without a copy constructor, you will just have 2 pointers pointing to the same address. 如果没有复制构造函数,您将只有2个指向同一地址的指针。 If the destructor of one deletes that memory, the other might not realize that the memory it's pointed to has gone away. 如果一个析构函数删除了那个内存,那么另一个可能没有意识到它所指向的内存已经消失了。 Equally important, you probably don't want one object writing into the other object's member :). 同样重要的是,您可能不希望一个对象写入另一个对象的成员:)。

暂无
暂无

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

相关问题 使用公共赋值运算符的私有副本ctor时出错 - Error when have private copy ctor with public assignment operator 为什么赋值运算符同时调用复制ctor和赋值运算符? - Why does assignment operator call both copy ctor and assignment operator? 当UDT包含零大小的数组时,无法生成copy-ctor或copy-assignment运算符 - Cannot generate copy-ctor or copy-assignment operator when UDT contains a zero-sized array 复制ctor和复制分配运算符const关键字位置 - Copy ctor and copy assignment operator const keyword position 依赖项没有复制构造函数或赋值运算符时的 C++ 初始化器列表 - C++ Initializer list when dependencies do not have copy ctor or assignment operator 在 C++ 中,我可以在定义自己的复制构造函数后跳过定义赋值运算符吗? - In C++, can I skip defining assignment operator after defining my own copy constructor? 有没有更简洁的方法来定义我的复制 ctor 与互斥锁? - Is there a cleaner way to define my copy ctor with a mutex? 构造函数在默认,参数化,复制ctor和赋值运算符的情况下的行为 - Constructor behavior in case of default, parameterized, copy ctor and assignment operator 复制ctor和赋值运算符中的任何陷阱都有略微不同的语义? - Any gotchas in copy ctor and assignment operator having slightly different semantics? 如何在地图中放置一个“删除”复制ctor和赋值运算符的类? - How to put a class that has “deleted” copy ctor and assignment operator in map?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM