何时删除复制构造函数

Posted

技术标签:

【中文标题】何时删除复制构造函数【英文标题】:When to delete copy constructor 【发布时间】:2017-04-12 10:49:14 【问题描述】:

我正在构建一个简单的神经网络,我有两个主要的类:NeuralNetwork 和 Level。我没有神经元,因为它是一个简单的前馈,一个级别中的所有单元共享相同的激活函数。

我以这种方式组织了我的关卡:

类 NeuralNetwork 有一个级别向量(不是指针,值。),为了快速访问它们,并且类 Level 的每个对象都有一个指向 prec 和下一个级别的指针,一些矩阵和东西。

更普遍的问题是: 对于像 Level 这样组织为双链表的类,应该使用哪些复制/移动构造函数/赋值运算符?

在 next 和 back 指针之后复制整个结构,并返回刚刚复制的对象的距离。

将单层复制留下指针 next\prec 到 nullptr 返回单例层,其中仅包含矩阵 ecc 的副本。

删除复制构造函数/赋值运算符。

【问题讨论】:

您好,欢迎来到 ***。请edit您的问题提供minimal reproducible example来说明您的问题。 无论做什么,请确保不存在不一致的对象。第二个选项听起来像一个不一致的对象,虽然你可以去添加一个 bool "is_valid" 或类似的,但话又说回来,如果结果不可用,为什么要允许复制。我将执行以下操作:暂时删除运算符并在您碰巧需要它时实施它(我假设删除是指使其非法使用,而不是删除代码)。如果没有,为什么要浪费时间写它?特别是因为如果您删除它,您的编译器将不会接受您不打算执行的复制分配。节省运行时间和内存。 适合您的目的。黄金法则是,当对象被破坏时,您需要确保它不会使任何现有对象失效。正确完成您提出的任何选项都可能是正确的。但是,您对所有数据进行深度复制的方法可能适合任何实验模型,但可能会在任何大型生产环境中产生性能开销。 【参考方案1】:

你的班级做什么取决于你。话虽如此,人们通常会期望诸如链表之类的通用容器是可复制的。

在设计此类类时,更一般地,问自己以下问题:

复制这个类是什么意思? 复制这个类有意义吗? 如果复制这个类,用户会感到惊讶吗?

如果不清楚复制此类的含义,请不要使其可复制。如果复制此类没有意义,请不要使其可复制。如果人们会惊讶地看到类被复制(想想 unique_ptr),不要在没有认真考虑的情况下让它可复制。这些不是硬性规则,这些只是一些思考点,可以帮助您找出合适的方法。

如果您不打算使某些内容可复制,那么删除关联的运算符确实很有意义(如果没有别的,这将作为文档)。

如果你确实让你的类可复制,那么你如何实现它取决于你。您可以制作写入时复制的共享实例,您可以急切地复制,您可以做任何您想做的事情;这一切都取决于您的用户(包括您)期望发生什么,以及每个人的权衡是什么。

【讨论】:

【参考方案2】:

“类 NeuralNetwork 有一个级别向量(不是指针,值。),为了快速访问它们,并且类 Level 的每个对象都有一个指向 prec 和下一个级别的指针”

这有点无意义。上一层是*(this-1),下一层是*(this+1)。那是因为 vector 连续存储其元素。当然,知道是否存在 上一层或下一层是一个小挑战,但这个问题往往不会出现。输入层是一个特殊层,因为您直接设置它的值。所有下一层都可以安全地从上一层拉取输入,因此没有一层需要将其输入推送到下一层。

训练有点困难,因为你有一个反向传播阶段,需要双向行走。但是,在这里您可以控制输入和所需的输出,因此您明确地使用 layers.front()layers.back(),永远不要超过它们。

现在,当您复制整个向量时,每一层都是一个副本,并且有一个新的this,但由于新向量再次连续,所以邻居的*(this-1)/*(this+1) 规则仍然成立。

【讨论】:

以上是关于何时删除复制构造函数的主要内容,如果未能解决你的问题,请参考以下文章

删除复制构造函数会破坏继承的构造函数

编译器何时不生成移动构造函数和移动赋值?

编译器何时为类的特殊成员提供定义?

了解 Lambda 闭包类型如何删除默认构造函数

访问控制对已删除的构造函数是不是重要?

在 C++ 中显式删除移动构造函数的用例 [关闭]