在我们公司的编码标准中,我们被告知“要注意防止(意外)复制的方法”。
我不太确定这意味着什么,但假设它们意味着如果不需要,我们应该停止复制类。
我能想到的是:
- 将类的复制构造函数设为私有。
- 将类的赋值运算符 (operator=) 设为私有。
- 使类的构造函数显式化(以阻止使用不正确的变量创建类)。
- 对于所有执行内存分配和需要复制的类,请确保复制构造函数和赋值运算符执行深复制而不是浅复制。
我走在正确的轨道上吗?有什么我可能错过的吗?
In our company's coding standard, we have been told to "be aware of the ways (accidental) copying can be prevented".
I am not really sure what this means, but assume that they mean we should stop classes from being copied if this is not required.
What I can think of is as follows:
- Make the copy constructor of a class private.
- Make the assignment operator (operator=) of a class private.
- Make the constructor of a class explicit (to stop classes from being created using incorrect variables).
- For all classes that carry out memory allocation and where copying is required, make sure that the copy constructor and assignment operator carry out deep copying rather than shallow copying.
Am I on the right track? Is there anything I might have missed out?
发布评论
评论(5)
是的,将赋值运算符和复制构造函数设置为私有将阻止您使用标准方法创建对象的任何副本(但如果您确实需要对象的副本,您可以实现,例如,Copy() 方法,它将执行深复制) 。
查看 boost::noncopyable。
更新(回复 Tal Pressman):
好吧,我认为任何意外复制都将使用赋值运算符或复制构造函数来执行。因此,使它们私有实际上是有意义的:如果对象复制是昂贵的操作,那么复制必须是显式的:其他开发人员可以无意中间接调用复制操作,编译器会通知他,这是禁止的。
Yes, making assignment operator and copy constructor private will prevent you from creating any copy of object using standart methods (but if you really need a copy of an object you can implement, for example, Copy() method, which will perform deep copy).
Take a look on boost::noncopyable.
Update (re to Tal Pressman):
Well, I presume, that any accidental copy will be performed using either assignment operator or copy constructor. So making them private actually makes sense: if object copying is costly operation, then copying must be explicit: other developer can unintentionally indirectly call copy op and compiler will inform him, that this is forbidden.
如果您的编码标准规定“注意可以防止(意外)复制的方法”,我猜他们不仅仅是在谈论防止类本身内的复制,而是在谈论不必要/意外复制的性能影响使用类。
对于刚接触 C++ 的人来说,代码中不必要的性能浪费的主要原因之一是不必要的复制(通常是通过临时复制)。编译器在决定何时不需要临时文件方面变得越来越好(请参阅 “想要速度?通过值传递”,感谢 Konrad 的评论),但最好的办法是了解 C++ 中复制和临时变量的内部工作原理(以及其他)。对我来说,阅读高效 C++ 确实让我开始了。
If your coding standard states "be aware of the ways (accidental) copying can be prevented", I'm guessing they aren't just talking about preventing copies from within the classes itself, but about the performance implications of unnecessary / accidental copies when using the classes.
One of the main causes of unnecessarily wasted performance in the code of people new to C++ is unnecessary copying, usually through temporaries. Compilers are getting better and better at deciding when temporaries are not necessary (see "Want speed? Pass by Value", thanks to Konrad's comment), but the best thing to do is to learn to be aware of the inner workings of copying and temporaries in C++ (among others). For me, reading Efficient C++ really got me started.
如果您正在使用 boost,那么防止类被复制的最简单方法是从 noncopyable:
它比手动将复制构造函数和赋值运算符设为私有使您的意图更清晰,并且具有相同的结果。
If you are using boost, then the easiest way to prevent a class from being copied is by deriving your class from noncopyable:
It makes your intention clearer than manually making the copy constructor and assigment operator private, and it has the same result.
你走在正确的轨道上。如果您不想使用 boost,您可以执行以下操作: 将复制构造函数和复制赋值运算符设为私有并且不实现它们。因此,如果您尝试复制实例,您将收到编译器错误。
You are on the right track. If you do not want to use boost you can do the following: Make copy constructor and copy assignment operator private and do not implement them. Thus you will get a compiler error if you try to copy an instance.
从避免错误的角度来看,您的列表看起来很棒,例如,由于对象隐式复制的共享指针而多次删除同一内存区域。
我希望这也是相关的;从“注意可以防止(意外)复制的方式”这句话中,您可能会认为这意味着“注意无意的不必要的复制”。这意味着可能影响性能的情况。在一个非常简单的示例中,您的编码约定可能意味着您应该更喜欢:
超过:
第二种情况将导致在调用赋值运算符(一种复制形式)以使用“填充text1”之前创建一个临时字符串来保存“某些文本”一些文字”。显然,这是一个简单的示例,良好的实践表明您应该尽可能使用构造函数初始化(第一个示例)。
Your list looks great from the point of view of avoiding errors, e.g. deleting the same area of memory more than once due to shared pointers from implicit copying of objects.
I hope this is also relevant; from the statement "be aware of the ways (accidental) copying can be prevented" you might take this to mean 'be aware of unintentional unnecessary copying'. This would mean circumstances which might affect performance. In a very simple example your coding conventions might mean you should prefer:
over:
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.