【问题标题】:Should one always define a copy constructor for deep copying pointers in a class with raw pointer members?是否应该始终为具有原始指针成员的类中的深度复制指针定义一个复制构造函数?
【发布时间】:2015-03-09 01:51:35
【问题描述】:

据我所知,理论上,如果一个类有一个原始指针成员,那么默认的复制构造函数会对该指针做一个浅拷贝,这样当原始对象被销毁时,拷贝中的指针成员就会有已删除它指向的值。这似乎意味着,除了出于某种原因我们想要限制复制的情况之外,任何具有原始指针成员的类都应该定义一个复制构造函数来对该指针进行深度复制。

我正在使用一个受人尊敬的第三方 API,并且我遇到了一个具有原始指针成员但没有定义复制构造函数的类,这使我对上述理解产生了怀疑。我错过了什么吗?

更新:第三方告诉我这个类不是要被复制的,因为这个对象代表一个视觉元素。他们指出他们应该创建一个私有副本构造函数。

【问题讨论】:

  • 这取决于原始对象的析构函数做了什么。如果它删除它,那么您的分析是正确的。他们很可能不希望按照您讨论的方式制作副本。
  • @ikegami:一个不可复制的类应该有一个复制构造函数,它可以是privatedeleted。我们在这里不能 100% 确定,但我阅读问题的方式也不是这样。
  • @ikegami:我没有声称你做到了。
  • 好吧,我再说一遍:并非所有的类都是为了处理复制尝试而编写的。这是一个特性,而特性需要付出努力(编码、测试、维护)。
  • @Jayz7522 当其他一些构造负责释放内存时(如果有必要的话)。例如,也许指针指向静态分配的东西。迭代器可能指向集合实现中的内部节点,但当迭代器被破坏时,它当然不应该删除它。

标签: c++ copy-constructor


【解决方案1】:

我认为std::reference_wrapper 是受人尊敬的 API(C++ 标准库)的一部分。它有一个复制构造函数,但不一定在实现代码中明确定义,因为它只是复制原始指针。所以你就是这样:拥有一个指针成员并不总是意味着所有权。

作为一个反例,一个你有非拥有指针成员但仍需要负责复制的例子,一个对象可以包含一个指向自身一部分的指针。如果复制这样的对象导致其内部指针指向其他对象的一部分,那就不好了。

总而言之,这取决于。必须经常需要定义的复制构造函数。但绝对不总是。


对于 C++03,三法则(或“三法则”)是一个经验法则,如果您需要析构函数、复制赋值运算符或复制构造函数,那么您可能需要全部三个。

所以检查是否存在复制赋值运算符或析构函数。在这种情况下,可能需要一个复制构造函数,并且缺少。

在 C++11 及以后,有人将其扩展为五定律,包括移动赋值运算符和移动构造函数,有人将其简化为零定律 strong>,要求所有所有权都应通过智能指针或集合对象来表示。

【讨论】:

  • 非常感谢。无知暴露:你能说,或者指点我说什么是非拥有指针,究竟是什么?这个名字有点直观,但我可以使用一些额外的清晰度。
  • 拥有指针的基本示例是,当该指针不再存在时,它指向的对象必须被销毁。 IE。指针拥有它所引用的对象。 std::unique_ptr 自动化了一种这样的单一所有权,其中指针不能被复制但可以移动。另一种方法是自动深拷贝、克隆,但标准库不支持。所有权可以共享,因此当指向对象的最后一个指针不复存在时,必须销毁该对象。 std::shared_ptr 使这种自动化。非拥有指针根本就​​没有拥有。纯参考。
【解决方案2】:

在理想情况下,任何原始指针成员都可以假定为非拥有指针。因为,如果你想要一个拥有指针,你就会使用智能指针!

非拥有指针成员将指向一个对象,该对象的生命周期在类外部进行管理,并且(按设计)应该比指针的生命周期长。

复制类时的默认行为是复制也指向同一个对象。这通常是您想要的行为。如果不是,是的,你将不得不改变这种行为。

当然,我们不是生活在一个理想的世界里,有很多地方使用拥有原始指针成员。在这种情况下,您是对的,默认的复制构造函数不合适(参见 Alf 关于 3/5 规则的回答)。

【讨论】:

    【解决方案3】:

    不,你没有错过任何东西。 一般。

    在不知道您在谈论什么库以及该类的语义是什么(已记录或以其他方式)的情况下,我不愿做出任何具体保证,但从表面上看,这听起来像是一个库错误。

    该类可能不拥有指针对象。如果它的构造函数没有分配它,而它的析构函数没有释放它,这很可能是这种情况。

    除此之外,你是对的。

    【讨论】:

      猜你喜欢
      • 2019-11-02
      • 1970-01-01
      • 1970-01-01
      • 2019-12-13
      • 2015-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多