首页 文章

为什么在三规则中不考虑非默认构造函数?

提问于
浏览
1

三规则(也称为三巨头或三巨头的规则)是C中的一个经验法则,声称如果一个类定义了下面的一个,它应该明确地定义所有三个:析构函数,复制构造函数,复制赋值运算符 .

为什么非默认构造函数不被视为其中之一?当在类中管理任何资源时,程序员必须始终定义非默认构造函数 .

4 回答

  • 0

    定义非默认构造函数并不意味着您需要析构函数等 - 您可能只是使用该构造函数来方便填充POD类型 .

    也就是说,这同样适用于默认构造函数 .

    基本上,当类将管理资源时会触发"do you need the big three?" . 您仍然可能不需要默认构造函数,但是您确实需要构造函数来设置有效的初始状态 .

    新构造的状态可能还没有资源的实例,但如果没有,则它必须知道它没有(例如,具有空指针) .

    然而,在很多情况下,三巨头也被隐含地使用 . 例如,Temporaries是默认构造的 . 您需要非默认构造函数的一个原因就是阻止提供和使用隐式默认构造函数 .

    因此,一次定义所有三个的一个原因是确保您的代码(包括编译器隐式提供的代码)保持理智 .

    几乎总是,如果你正在管理一个资源,你将拥有一个默认的构造函数,这就是规则提到的原因 - 但只要你定义某种构造函数,你应该没问题 .

  • 8

    为什么非默认构造函数不被视为其中之一?当在类中管理任何资源时,程序员必须始终定义非默认构造函数 .

    这不一定是真的 . 构造函数可能不会获取任何资源 . 其他功能也可能会获取它们 . 事实上,可能有许多函数(包括构造函数本身)可能会获取资源 . 例如,在 std::vector<T> 的情况下,获取资源的是 resize()reserve() . 因此,考虑构造函数就像可能获取资源的其他函数一样 .

    这个规则的想法是,当你复制时,编译器生成的默认复制代码对于哪个函数获取它是不正确的,析构函数必须释放它,因为析构函数保证被执行,对于完全构造的对象 . 因此,你也可以实现移动语义 . move-semantic的逻辑参数与copy-semantics的逻辑参数相同,只是在移动语义中,你也改变了源代码 . 移动语义很像器官捐赠者;当你把器官交给别人时,你就不再拥有它了 .

  • 2

    这不是三个规则的含义 .

    管理资源的任何类都将具有该析构函数,因此无论如何都适用三种规则 . 关键是你并不一定需要非默认的构造函数,但你确实需要其他的(复制构造函数/赋值运算符) .

    至少它曾经是至关重要的,例如标准容器中的元素 .

    现在有了移动语义(c 11),事情开始有所改变 . 是否会有5的规则?我不知道它将如何在“最佳实践”和“经验法则”方面发挥作用 .

    事实上,人们已经可以陈述三元规则的变体:定义析构函数的类也应该定义一个复制/移动构造函数和复制/移动赋值运算符 . AND如果定义了复制构造函数,则还应定义复制赋值运算符 . 如果定义了移动构造函数,则还应定义移动赋值运算符 .

    无论如何,这将是我的一段时间的经验法则 .

  • 0

    如果您获取任何资源(例如使用new),那么您就完全正确了,但我们假设您不会忘记在析构函数中释放资源 . 一旦你创建了析构函数,三个规则就会启动,你应该定义所有三个 .

    但是,例如,如果您在类中只有一些使用复制语义初始化的成员变量,则不需要析构函数,并且该规则不适用 .

相关问题