我在看CppCon2014, Michael Caisse, The Canonical Class talk
在28'31“,他显示了一个图表,显示用户何时提供了一些复制控件,编译器将如何隐式提供或不提供其余控件:

c++ - 为什么当用户提供 move 构造函数或 move 分配时,将删除复制构造函数和复制分配?-LMLPHP

我不太了解带有“删除”的单元格-似乎标准说,当用户提供move构造函数或move分配时,副本构造函数和copy分配将被删除-好的,但是为什么?

让我们更具体一些。

Q1。当用户提供move构造函数时,将删除副本构造函数和副本构造函数-是否这样做是为了避免错误使用,即为构造函数或赋值提供了左值,左值无效?这是否显式强制将作为rvalue传递给构造函数或赋值的参数?

Q2。当用户提供移动分配时,副本分配将被删除-这与Q1相同吗?

Q3。当用户提供移动分配时,副本构造函数将被删除-
为什么这样?移动分配似乎不会与副本构造函数混淆?

最佳答案

考虑到一些不幸的历史,这是最不安全的方法。

用户定义析构函数的原因只有一个,那就是我们正在管理本身不是RAII的资源。如果我们正在管理资源,它将无法很好地复制自身(或移动自身)。这些操作将需要手动管理。

如果要提供析构函数,那么该语言确实应该隐式删除copy和move运算符。不幸的是,这在早期并没有预见到,因此我们有3条规则:“如果定义了析构函数,则必须定义拷贝构造函数和拷贝分配”。

这条规则是为了使我们免受语言障碍。

有人提议关闭此漏洞(IIRC),据我所知,它被拒绝了,因为它会破坏太多的现有代码(尽管坦率地说,所有这些现有代码都存在危险的错误,这并不是一件坏事。 )。

所以我们就在这里。原则是,如果要手动管理资源,则必须在所有5个操作中对其进行管理。如果手动编写这些操作之一,则应全部编写。

只是为了自动删除副本构造函数/副本分配,该语言仍然无法使用。

当然,答案是永远不要手动管理资源。由于我们具有带有自定义删除器的智能指针,可以为我们管理资源,因此我们几乎不需要。当我们这样做时,我们应用5、3 ...的规则,但我们始终应该首选无规则-使用托管资源并且不要定义任何析构函数,复制,移动或赋值运算符,只需让编译器正确执行即可事情。

关于c++ - 为什么当用户提供 move 构造函数或 move 分配时,将删除复制构造函数和复制分配?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39425782/

10-11 22:43
查看更多