在`dctor、copy ctor和copy assignment operator`中,为啥删除一个而让另一个隐式定义最有可能导致错误
Posted
技术标签:
【中文标题】在`dctor、copy ctor和copy assignment operator`中,为啥删除一个而让另一个隐式定义最有可能导致错误【英文标题】:Among `dctor,copy ctor and copy assignment operator`, why deletes one and leaves the other to be implicitly-defined will most likely result in errors在`dctor、copy ctor和copy assignment operator`中,为什么删除一个而让另一个隐式定义最有可能导致错误 【发布时间】:2020-09-17 22:09:39 【问题描述】:根据文档(https://en.cppreference.com/w/cpp/language/rule_of_three),其中说:
通过可复制句柄管理不可复制资源的类 可能必须声明复制赋值和复制构造函数私有和 不提供它们的定义或将它们定义为已删除。这是 三法则的另一种应用:删除一个并离开 其他要隐式定义的很可能会导致错误。
作为主题,我想知道它为什么会发生。有人可以更详细地解释一下吗? 有人可以举一些简单的例子说清楚吗?
【问题讨论】:
【参考方案1】:答案在上一段:
如果类管理的资源的句柄是非类类型的对象(原始指针、POSIX 文件描述符等),其析构函数不执行任何操作并复制构造函数/赋值,则隐式定义的特殊成员函数通常是不正确的运算符执行“浅复制”(复制句柄的值,而不复制底层资源)。
三法则告诉您,您希望所有特殊成员(复制构造函数、复制赋值运算符和析构函数)都以相同的方式定义:隐式、显式或根本不定义。
管理不可复制资源的类通常是拥有一些难以复制资源的类。一个例子是std::filebuf
,它管理一个文件(它被std::fstream
使用)。它没有定义复制构造函数或复制赋值运算符:两者都被删除。它确实明确定义了一个析构函数以关闭文件。
现在,如果隐式定义析构函数,文件将永远不会关闭,缓冲区将留在内存中,从而导致内存泄漏。如果复制赋值运算符的复制构造函数是隐式定义的,它会将指针复制到缓冲区,然后可能会为同一个文件多次调用析构函数,尝试多次删除同一个缓冲区(即未定义的行为)。
【讨论】:
以上是关于在`dctor、copy ctor和copy assignment operator`中,为啥删除一个而让另一个隐式定义最有可能导致错误的主要内容,如果未能解决你的问题,请参考以下文章
用户定义的 Copy ctor 和 copy-ctors 进一步向下链编译器错误?程序员脑筋急转弯?
std::any 用于仅移动模板,其中 copy-ctor 内的 static_assert 等于编译错误,但为啥呢?
当使用 operator=() 时使用 copy-ctor 的 C++ - 这究竟是如何工作的?