【发布时间】:2011-01-29 12:57:45
【问题描述】:
我有一个可能包含许多顶点的 Shape 类,我正在考虑将复制构造函数/复制分配设为私有,以防止意外不必要地复制我的重量级类(例如,通过值而不是通过引用传递)。
要制作 Shape 的副本,必须故意调用“克隆”或“复制”方法。
这是好的做法吗?我想知道为什么 STL 容器不使用这种方法,因为我很少想按值传递它们。
【问题讨论】:
标签: c++ noncopyable
我有一个可能包含许多顶点的 Shape 类,我正在考虑将复制构造函数/复制分配设为私有,以防止意外不必要地复制我的重量级类(例如,通过值而不是通过引用传递)。
要制作 Shape 的副本,必须故意调用“克隆”或“复制”方法。
这是好的做法吗?我想知道为什么 STL 容器不使用这种方法,因为我很少想按值传递它们。
【问题讨论】:
标签: c++ noncopyable
限制您的用户并不总是一个好主意。仅仅记录复制可能很昂贵就足够了。如果用户真的想复制,那么通过提供复制构造函数来使用 C++ 的本机语法是一种更简洁的方法。
因此,我认为真正的答案取决于上下文。也许你正在编写的真实类(而不是想象中的 Shape)不应该被复制,也许它应该被复制。但作为一种通用方法,我当然不能说应该通过强制用户使用显式方法调用来阻止用户复制大型对象。
【讨论】:
恕我直言,是否提供复制构造函数和赋值运算符更多地取决于您的类建模的内容,而不是复制的成本。
如果你的类代表值,也就是说,如果传递一个对象或对象的副本没有任何区别,那么提供它们(并提供相等运算符)
如果您的类不是,也就是说,如果您认为该类的对象具有身份和状态(也有人说 entities),请不要。如果副本有意义,请为其提供克隆或副本成员。
有时您无法轻松分类某些类别。容器在那个位置。将它们视为实体并仅通过引用传递它们并具有特殊操作以在需要时进行复制是有意义的。您也可以将它们简单地视为值的聚合,因此复制是有意义的。 STL 是围绕值类型设计的。由于一切都是价值,因此容器是有意义的。这允许像map<int, list<> > 这样有用的东西。 (请记住,您不能将不可复制的类放入 STL 容器中)。
【讨论】:
通常,您不会因为类很重而使类不可复制(您已经展示了一个很好的 STL 示例)。
当它们连接到一些不可复制的资源(如套接字、文件、锁)或它们根本不设计被复制时(例如,有一些内部结构可以很难被深度复制)。
但是,在您的情况下,您的对象是可复制的,所以保留它。
关于clone()的小记——它被用作多态复制构造函数——它有不同的
含义和用法不同。
【讨论】:
大多数程序员已经意识到复制各种对象的成本,并且知道如何使用传递引用等技术来避免复制。
请注意,STL 的向量、字符串、映射、列表等都可以被视为“重量级”对象(尤其是像具有 10,000 个元素的向量!)。这些类都仍然提供复制构造函数和赋值操作符,所以如果你知道你在做什么(比如制作一个 std::list 向量),你可以在必要时复制它们。
因此,如果它有用,无论如何都要提供它们,但一定要记录它们是昂贵的操作。
【讨论】:
根据您的需要...
如果您想确保副本不会错误地发生,并且制作副本会导致严重的瓶颈或根本没有意义,那么这是一种很好的做法。编译错误比性能调查要好。
如果您不确定您的课程将如何使用,并且不确定这是否是一个好主意,那么这不是一个好习惯。大多数时候你不会以这种方式限制你的课程。
【讨论】: