在“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

提问人:sunshilong369 提问时间:5/30/2020 更新时间:5/30/2020 访问量:50

问:

根据文档(https://en.cppreference.com/w/cpp/language/rule_of_three),其中说:

通过可复制句柄管理不可复制资源的类 可能必须声明 copy assignment 和 copy 构造函数 private,并且 不提供其定义或将其定义为已删除。这是 三法则的另一个应用:删除一个并保留 其他隐式定义很可能会导致错误。

作为主题,我想知道为什么会这样。sombody可以更详细地解释一下吗? 有人可以通过举一些简单的例子来说明吗?

C++ C++11 复制构造函数 赋值运算符

评论


答:

1赞 Nelfeal 5/30/2020 #1

答案在上一段:

如果类管理的资源是非类类型的对象(原始指针、POSIX 文件描述符等),其析构函数不执行任何操作,并且复制构造函数/赋值运算符执行“浅层复制”(复制句柄的值,而不复制基础资源),则隐式定义的特殊成员函数通常不正确。

三法则告诉你的是,你希望所有特殊成员(复制构造函数、复制赋值运算符和析构函数)都以相同的方式定义:隐式、显式或根本不定义。

管理不可复制资源的类通常是拥有某些难以复制资源的类。一个例子是 std::filebuf,它管理一个文件(它由 )。它既不定义复制构造函数,也不定义复制赋值运算符:两者都被删除。它确实显式定义了一个析构函数以关闭文件。std::fstream

现在,如果析构函数是隐式定义的,则文件将永远不会关闭,缓冲区将保留在内存中,从而导致内存泄漏。如果隐式定义了复制赋值运算符的复制构造函数,则它会将指针复制到缓冲区,然后可能会为同一文件多次调用析构函数,从而多次尝试删除同一缓冲区(这是未定义的行为)。