首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >应宣布哪些必要的特殊成员职能?

应宣布哪些必要的特殊成员职能?
EN

Stack Overflow用户
提问于 2017-03-31 19:09:56
回答 3查看 780关注 0票数 0

我目前正在学习C++。我了解了一些由编译器生成的特殊成员函数。

·默认构造函数。·复制构造函数·移动构造器·复制赋值操作符·移动赋值操作符·析构函数

我知道每个成员函数的功能。但我想知道哪些成员函数是必需的,应该声明(而不是由编译器生成),作为良好编码实践的一部分,记住内存和效率。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-03-31 20:34:13

默认构造函数是其中的一个特例。如果某些成员变量需要的初始状态不是这些成员的默认值,则编写默认构造函数。

剩下的这些只有在你知道你需要它的时候才能被覆盖。

在这些情况下,您可能希望编写列出的函数的自定义版本:

  1. 类的成员变量是指向它所分配的动态内存的指针。
  2. 您的类有数据结构作为成员,用户不希望将已完成的版本传递给构造函数。
  3. 您的类有您不想使用默认副本模型的成员(例如,您想要一个深拷贝,但是复制构造函数或赋值将生成一个浅拷贝)。
  4. 您的类有一个静态数据成员,在创建它的新实例时应该对其进行更改。

每个用例的示例包括:

  1. STL向量,它动态地分配其基础数组并在其析构函数中释放。
  2. STL列表,它将添加到列表节点中的数据复制到列表节点上,其内部元素不向最终用户公开。
  3. 任何STL容器类都是一个很好的例子。
  4. 需要访问昂贵资源的东西的数量。类似于std::shared_ptr的设计目标。

如果一个类满足了太多的这些需求,您可能应该考虑更改您的设计,以使用更多的容器--标准库提供的实用程序。特别是如果一个类需要第四个属性,而另一个类需要其他三个属性。与第1至3点和第4点有关的责任应由不同类别处理.重要的是要注意,拥有一种巨大的、昂贵的资源和拥有许多资源是不同类型的责任。

参考文献:

  • 三/五规则的解释
  • STL容器类的列表
票数 1
EN

Stack Overflow用户

发布于 2017-03-31 19:23:07

但是我希望这些成员函数中的哪一个是必需的,应该声明(而不是由编译器生成)。

如果隐式生成的特殊成员函数执行您的意愿,则不应显式声明它们。

如果一些其他生成的特殊成员函数没有按照您的意愿执行,那么您必须显式地声明它们,并提供所需的实现。

如果您有任何析构函数的显式非平凡定义,复制/移动构造函数/赋值,那么作为经验规则,您可能需要为每个析构函数定义一个定义。

票数 1
EN

Stack Overflow用户

发布于 2017-03-31 19:33:15

默认构造函数在这里是个奇怪的人。是否有默认构造并不一定与是否编写其他构造函数有任何关系(尽管在实践中,编写没有默认构造函数的移动构造函数是困难的)。

在大多数情况下,您应该尝试遵循零规则(http://www.nirfriedman.com/2015/06/27/cpp-rule-of-zero/),这意味着您不会为类编写任何这些成员函数。相反,选择正确表达各种资源所需的所有权语义的成员。成员std::vector正确地以您希望的方式处理复制和移动,因此具有此类成员的类不一定需要任何特殊成员。但是,如果您尝试使用用new[]创建的原始指针作为数组,则需要处理许多这些问题,并且需要编写特殊的成员函数。

如果你需要写一个,你应该明确地考虑所有的问题,但这并不意味着你必须把它们都写好。有时,您可能想要=default=delete其中的一些。一个简单的例子:

代码语言:javascript
复制
template <class T>
copy_ptr {
  copy_ptr() = default;
  copy_ptr(copy_ptr&&) = default;
  copy_ptr& operator=(copy_ptr&&) = default;

  copy_ptr(const copy_ptr& other)
    : m_resource(make_unique<T>(*other.m_resource)
 {}

 copy_ptr& operator=(const copy_ptr& other) {
   m_resource = make_unique<T>(*other.m_resource);
 }
 // define operator*, etc

  std::unique_ptr<T> m_resource;
};

这是一个指针,它不是像unique_ptr那样不可复制的,而是对它所持有的对象进行深度复制。但是,我们能够使用unique_ptr中的默认构造函数、移动运算符和析构函数"as-is“,所以我们默认了它们。我们只重写了复制操作,完成了最小的工作。

基本上,在C++中使用特殊运算符的想法是将它们“向下”推到较小的对象/类中。它们通常单独负责管理该资源。协调业务逻辑的更大类应该非常努力地将资源管理问题推迟到成员身上。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43148012

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档