防止C ++中的意外对象复制

时间:2009-08-27 09:27:36

标签: c++ copying

在我们公司的编码标准中,我们被告知“要知道可以防止复制的方式(意外)”。

我不确定这意味着什么,但假设它们意味着如果不需要,我们应该停止复制类。

我能想到的是:

  1. 使类的复制构造函数成为私有。
  2. 使类的赋值运算符(operator =)成为私有。
  3. 使类的构造函数显式化(以阻止使用不正确的变量创建类)。
  4. 对于执行内存分配以及需要复制的所有类,请确保复制构造函数和赋值运算符执行深度复制而不是浅复制。
  5. 我是否在正确的轨道上?有什么我可能错过的吗?

5 个答案:

答案 0 :(得分:21)

是的,将赋值运算符和复制构造函数设置为私有将阻止您使用标准方法创建任何对象副本(但如果您确实需要可以实现的对象的副本,例如,Copy()方法,它将执行深刻的复制)。

查看boost::noncopyable

更新(请访问Tal Pressman):

  

......你应该注意这些事情并注意你不要意外地复制你不应该的东西。

嗯,我认为,任何意外副本都将使用赋值运算符或复制构造函数执行。因此,将它们设为私有实际上是有意义的:如果对象复制是昂贵的操作,那么复制必须是明确的:其他开发人员可以无意间接调用复制操作,编译器将通知他,这是禁止的。

答案 1 :(得分:10)

如果您使用的是boost,那么阻止类被复制的最简单方法是从noncopyable派生您的类:

#include <boost/noncopyable.hpp>

class Foo : private boost::noncopyable
{
}

它使您的意图比手动使复制构造函数和赋值运算符更加清晰,并且它具有相同的结果。

答案 2 :(得分:10)

如果你的编码标准声明“要知道可以防止复制的方式(意外)”,我猜他们不只是在谈论防止类本身内的副本,而是关于不必要的性能影响/ 使用类时的意外复制。

在C ++新手的代码中不必要地浪费性能的一个主要原因是不必要的复制,通常是通过临时工具。编译器在决定何时不需要临时工具时越来越好(参见"Want speed? Pass by Value",感谢Konrad的评论),但最好的办法是学会了解C ++中复制和临时工作的内部工作原理(除其他外)。对我来说,阅读Efficient C++真的让我开始了。

答案 3 :(得分:2)

你走在正确的轨道上。如果您不想使用boost,则可以执行以下操作:将复制构造函数和复制赋值运算符设为私有,并且不实现它们。因此,如果您尝试复制实例,则会出现编译器错误。

答案 4 :(得分:0)

从避免错误的角度来看,您的列表看起来很棒,例如:由于隐式复制对象的共享指针,多次删除相同的内存区域。

我希望这也是相关的;从声明“意识到可以防止复制的方式(意外)”你可能会认为这意味着'意识到无意的不必要的复制'。这将意味着可能影响性能的情况。在一个非常简单的例子中,您的编码约定可能意味着您应该更喜欢:

std::string text1( "some text" );

在:

std::string text1 = "some text";

第二种情况会导致创建一个临时字符串,以便在调用赋值运算符(一种复制形式)之前保存“某些文本”,以使用“some text”填充text1。显然这是一个简单的例子,良好的实践将决定你应该尽可能使用构造函数初始化(第一个例子)。