我有一个可能包含许多顶点的 Shape 类,并且我正在考虑将复制构造函数/复制赋值设为私有,以防止意外地不必要地复制我的重量级类(例如,按值传递而不是按引用传递)。
要制作 Shape 的副本,必须特意调用“克隆”或“复制”方法。
这是好的做法吗?我想知道为什么 STL 容器不使用这种方法,因为我很少想按值传递它们。
I have a Shape class containing potentially many vertices, and I was contemplating making copy-constructor/copy-assignment private to prevent accidental needless copying of my heavyweight class (for example, passing by value instead of by reference).
To make a copy of Shape, one would have to deliberately call a "clone" or "duplicate" method.
Is this good practice? I wonder why STL containers don't use this approach, as I rarely want to pass them by value.
发布评论
评论(5)
一般来说,您不会仅仅因为类很重(您已经展示了一个很好的示例 STL)而将它们设置为不可复制。
当它们连接到某些不可复制的资源(如套接字、文件、锁)或者它们根本不是设计来复制的(例如,有一些很难深的内部结构)时,您将它们设置为不可复制复制)。
但是,在您的情况下,您的对象是可复制的,因此请将其保留为这样。
关于
clone()
的小注释——它被用作多态复制构造函数——它有不同的地方含义和用法不同。
Generally, you do not make classes non-copyable just because they are heavy (you had shown a good example STL).
You make them non-copyable when they connected to some non-copyable resource like socket, file, lock or they are not designed to be copied at all (for example have some internal structures that can be hardly deep copied).
However, in your case your object is copyable so leave it as this.
Small note about
clone()
-- it is used as polymorphic copy constructor -- it has differentmeaning and used differently.
大多数程序员已经意识到复制各种对象的成本,并且知道如何使用引用传递等技术来避免复制。
请注意,STL 的向量、字符串、映射、列表等都可以被不同地视为“重量级”对象(尤其是像具有 10,000 个元素的向量这样的对象!)。这些类仍然提供复制构造函数和赋值运算符,因此如果您知道自己在做什么(例如创建向量的 std::list ),则可以在必要时复制它们。
因此,如果有用,无论如何都提供它们,但一定要记录它们是昂贵的操作。
Most programmers are already aware of the cost of copying various objects, and know how to avoid copies, using techniques such as pass by reference.
Note the STL's vector, string, map, list etc. could all be variously considered 'heavyweight' objects (especially something like a vector with 10,000 elements!). Those classes all still provide copy constructors and assignment operators, so if you know what you're doing (such as making a std::list of vectors), you can copy them when necessary.
So if it's useful, provide them anyway, but be sure to document they are expensive operations.
根据您的需求...
如果您想确保不会错误地进行复制,并且制作副本会导致严重的瓶颈或根本没有意义,那么这是一个很好的做法。编译错误比性能调查更好。
如果您不确定您的课程将如何使用,并且不确定这是否是一个好主意,那么这不是一个好的做法。大多数时候你不会以这种方式限制你的班级。
Depending on your needs...
If you want to ensure that a copy won't happen by mistake, and making a copy would cause a severe bottleneck or simply doesn't make sense, then this is good practice. Compiling errors are better than performance investigations.
If you are not sure how your class will be used, and are unsure if it's a good idea or not then it is not good practice. Most of the time you would not limit your class in this way.
限制用户并不总是一个好主意。只需记录复制可能会很昂贵就足够了。如果用户确实想要复制,那么通过提供复制构造函数来使用 C++ 的本机语法是一种更简洁的方法。
因此,我认为真正的答案取决于上下文。也许您正在编写的真实类(而不是虚构的 Shape)不应该被复制,也许应该复制。但作为一种通用方法,我当然不能说应该通过强制用户使用显式方法调用来阻止用户复制大型对象。
Restricting your users isn't always a good idea. Just documenting that copying may be expensive is enough. If a user really wants to copy, then using the native syntax of C++ by providing a copy constructor is a much cleaner approach.
Therefore, I think the real answer depends on the context. Perhaps the real class you're writing (not the imaginary Shape) shouldn't be copied, perhaps it should. But as a general approach, I certainly can't say that one should discourage users from copying large objects by forcing them to use explicit method calls.
恕我直言,是否提供复制构造函数和赋值运算符更多地取决于您的类建模的内容,而不是复制的成本。
如果你的类代表值,也就是说,如果传递一个对象或对象的副本没有什么区别,那么提供它们(并提供相等运算符)
如果你的类不是,也就是说,如果您认为该类的对象具有身份和状态(也称为实体),则不然。如果副本有意义,请为其提供克隆或副本成员。
有时有些类您无法轻松分类。容器就处于这个位置。将它们视为实体并仅通过引用传递它们并在需要时进行特殊操作来制作副本是有意义的。您也可以将它们简单地视为值的聚合,因此复制是有意义的。 STL 是围绕值类型设计的。由于一切都有价值,因此容器如此也是有道理的。这允许像
map 这样的东西>
很有用。 (请记住,您不能将不可复制的类放入 STL 容器中)。IMHO, providing a copy constructor and assignment operator or not depend more of what your class modelizes than the cost of copying.
If your class represent values, that is if passing an object or a copy of the object doesn't make a difference, then provide them (and provide the equality operator also)
If your class isn't, that is if you think that object of the class have an identity and a state (one also speak of entities), don't. If a copy make sense, provide it with a clone or copy member.
There are sometimes classes you can't easily classify. Containers are in that position. It is meaninfull the consider them as entities and pass them only by reference and have special operations to make a copy when needed. You can also consider them simply as agregation of values and so copying makes sense. The STL was designed around value types. And as everything is a value, it makes sense for containers to be so. That allows things like
map<int, list<> >
which are usefull. (Remember, you can't put nocopyable classes in an STL container).