在`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++ - 这究竟是如何工作的?

boost::filesystem::directory_iterator copy-ctor 隐式删除

chrome的功能Copy as cURL

[20171121]rman backup as copy 2.txt