在我们公司的编码标准中,我们被告知要“注意可以防止(意外)复制的方法”。
我不太确定这意味着什么,但假设它们意味着如果不需要,我们应该停止复制类。
我能想到的如下:
- 将类的复制构造函数设为私有。
- 将类的赋值运算符 (operator=) 设为私有。
- 使类的构造函数显式(以阻止使用不正确的变量创建类)。
- 对于所有执行内存分配和需要复制的类,请确保复制构造函数和赋值运算符执行深复制而不是浅复制。
我在正确的轨道上吗?有什么我可能错过的吗?
是的,将赋值运算符和复制构造函数设为私有将阻止您使用标准方法创建任何对象副本(但如果您确实需要可以实现的对象副本,例如 Copy() 方法,它将执行深度复制) .
更新(回复 Tal Pressman):
...您应该注意这些事情并注意不要意外复制您不应该复制的对象。
好吧,我假设任何意外复制都将使用赋值运算符或复制构造函数来执行。所以将它们设为私有实际上是有道理的:如果对象复制是昂贵的操作,那么复制必须是显式的:其他开发人员可以无意中间接调用复制操作,编译器会通知他,这是被禁止的。
如果您使用的是 boost,那么防止类被复制的最简单方法是从noncopyable派生您的类:
#include <boost/noncopyable.hpp>
class Foo : private boost::noncopyable
{
}
它使您的意图比手动将复制构造函数和赋值运算符设为私有更清晰,并且具有相同的结果。
如果您的编码标准规定“注意可以防止(意外)复制的方式”,我猜他们不仅仅是在谈论防止类本身的复制,而是关于不必要/意外复制的性能影响使用类。
C++ 新手在代码中不必要地浪费性能的主要原因之一是不必要的复制,通常是通过临时复制。编译器在决定何时不需要临时文件方面变得越来越好(请参阅“想要速度?通过价值”,感谢 Konrad 的评论),但最好的办法是学习了解复制和临时文件的内部工作原理在 C++ 中(等等)。为了我,
你在正确的轨道上。如果您不想使用 boost,您可以执行以下操作:将复制构造函数和复制赋值运算符设为私有并且不要实现它们。因此,如果您尝试复制实例,您将收到编译器错误。
从避免错误的角度来看,您的列表看起来很棒,例如,由于来自对象的隐式复制的共享指针,多次删除相同的内存区域。
我希望这也是相关的;从“注意可以防止(意外)复制的方式”的声明中,您可能会认为这意味着“注意无意的不必要的复制”。这将意味着可能影响性能的情况。在一个非常简单的示例中,您的编码约定可能意味着您应该更喜欢:
std::string text1( "some text" );
超过:
std::string text1 = "some text";
The second case would result in a temporary string being created to hold "some text" before the assignment operator is invoked (a form of copying) to populate text1 with "some text". Obviously this is a trivial example and good practice would dictate that you should use the constructor initialisation (first example) where ever possible.