问题标签 [rule-of-zero]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
3 回答
933 浏览

c++ - 无法理解零规则中的 C++11 语法

我正在研究零规则,并有 2 个问题用于演示该规则的最后一段代码。

  1. 为什么使用大括号而不是括号来初始化句柄?
  2. 什么 using module_handle = std::unique_ptr; 在这种情况下到底是什么意思?可以用typedef替换它吗?
0 投票
1 回答
1395 浏览

c++ - “零规则”是否也适用于具有虚拟方法的类?

我发现Peter Sommerlads 幻灯片(p.32)中也提到的零规则非常引人注目。

虽然,我似乎记得有一个严格的规则,即必须定义析构函数 virtual如果该类具有虚拟成员并且实际上是派生的。

析构函数的主体甚至可能是空的(它只需要 vtbl 中的条目)。

我似乎记得在使用层次结构时

那么delete obj 调用正确的析构函数很重要。是否正确,如果我完全省略了析构函数定义,它就不会变成 virtual,因此会调用错误的 d'tor 吗?

这引出了我的最后一个问题:

  • “零规则”在具有虚拟方法的层次结构中是否也适用
  • 还是在这些情况下我需要定义虚拟析构函数?

编辑:正如我在回答中被提醒的那样,我的 1sr 版本的问题有错误的假设。相关的(虚拟)析构函数是 in Base,而不是Derived。但我的问题是:我是否需要声明(虚拟)析构函数?

0 投票
3 回答
3195 浏览

c++ - C++ 零规则:多态删除和 unique_ptr 行为

在最近的超载期刊中,主题为Enforcing the rule of zero,作者描述了我们如何避免编写五个运算符的规则,因为编写它们的原因是:

  1. 资源管理
  2. 多态性缺失

这两个都可以通过使用智能指针来处理。

在这里,我对第二部分特别感兴趣。

考虑以下代码片段:

在这种情况下,正如文章作者所解释的,我们通过使用共享指针来实现多态删除,这确实有效。

但是如果我shared_ptr用 a替换unique_ptr,我将不再能够观察到多态删除。

现在我的问题是,为什么这两种行为不同?为什么不shared_ptr处理多态删除unique_ptr

0 投票
1 回答
565 浏览

c++ - unique_ptr、自定义删除器和零规则

我正在编写一个使用 C 接口创建的两个对象的类。对象看起来像:

(对于 类似bar_t)。因为 C++11,我想将它们包装在一个智能指针中,这样我就不必编写任何特殊方法。该类将拥有两个对象的唯一所有权,因此在unique_ptr逻辑上是有意义的......但我仍然需要编写一个构造函数:

另一方面,使用shared_ptr,我不必编写构造函数或使用类型别名,因为我可以delete_foo传入reset()- 尽管这会使我的可MyClass复制并且我不想要那样。

MyClass使用unique_ptr语义编写并仍然遵守零规则的正确方法是什么?

0 投票
1 回答
712 浏览

c++ - 理解零规则

我有一个基类,我不想让派生类可复制。为了使一切明确,我以这种方式实现它:

这是做这些事情的正确方法吗?根据我的知识和阅读的内容,答案是肯定的,但在将其引入生产系统之前,我想确定一下。


编辑

得出结论:1)几乎总是不应该删除移动运算符。那是因为“有无数种东西需要可移动性”。2)对于抽象基类,允许编译器生成特殊的成员函数,并在必要时将删除移到派生类中会更安全。

0 投票
4 回答
3619 浏览

c++ - 为什么析构函数会禁用隐式移动方法的生成?

通过阅读此博客,我试图了解零规则的含义。IMO,它说如果您声明自己的析构函数,那么不要忘记将移动构造函数和移动赋值作为默认值。

示例

“添加析构函数的副作用是禁止生成移动函数,但由于 Widget 是可复制的,所有用于生成移动的代码现在都会生成副本。也就是说,在类中添加析构函数可能会导致- 用可能效率较低的副本默默地取代高效的举措”。

Scott Meyers 的上述文字,在引号内引起了我的一些问题:

  • 为什么声明析构函数会隐藏移动语义?
  • 声明/定义析构函数是否仅隐藏移动语义或复制构造函数和复制分配以及隐藏移动语义?
0 投票
1 回答
1009 浏览

c++ - C ++零规则和什么是“用户声明的”构造函数?

Orbit 澄清 Lightness Races 之后,我缩小了我的帖子范围。

看完这篇文章:零法则

我明白了最多,但我仍然想解决我遇到的一些不清楚的问题:

1.看这句话:

如果类 X 的定义没有显式声明移动构造函数,则当且仅当以下情况时才会隐式声明为默认构造函数:

X 没有用户声明的复制构造函数,并且

X 没有用户声明的复制赋值运算符,

X 没有用户声明的移动赋值运算符,

X 没有用户声明的析构函数,并且

移动构造函数不会被隐式定义为已删除。

应该所有 5 个语句共存(共享“和”关系)还是仅其中一些(共享“或”关系)?

2.用户声明的”复制构造函数\复制赋值操作符...是什么意思?

  • 是在 .h 文件中声明它(上面的列表中的任何一个),但没有实现它被认为是用户声明的?

  • 是在 .h 文件中声明它(上面列表中的任何一个)并指定“ =deleted ”或“ =default ”被认为是用户声明的?

  • 是在 .h 文件中声明它(上面列表中的任何一个),其中包含空手镯 {},被认为是用户声明的?

尊敬,

易泰

0 投票
1 回答
264 浏览

c++ - 只需添加什么都不做的析构函数会导致编译错误(围绕std :: move),为什么?

在学习的过程std::move中,我发现了一个奇怪的问题。

如果我只添加一个对完美程序没有任何作用的析构函数,我会得到一个编译错误。

实时代码:https ://ideone.com/UTR9ob

错误是 invalid initialization of non-const reference of type 'B&' from an rvalue of type 'std::remove_reference<B&>::type {aka B}'

问题:

  • (1) 哪些 C++ 语法规则强制执行该规则?换句话说,错误是什么意思?
  • (2) 如果我想添加几乎什么都不做的析构函数(例如只打印调试日志)B,我真的必须遵循五规则吗?如果没有,如何编译?在我看来,仅仅因为这个而遵循五法则太乏味和肮脏。

我认为零规则只是一个好习惯。

但是,从这个例子来看,在我看来这是一个硬性规则,如果违反,我会得到编译错误。

0 投票
2 回答
819 浏览

c++ - 零规则与基类析构函数

我有一个基类Base和一个派生类D,我希望编译器为我自动生成移动构造函数和移动赋值运算符。遵循零规则,我将所有内存管理留给编译器,并且只使用 2 级类(没有原始指针、数组等):

应该是这个吧?

输入C++ 核心指南

基类析构函数应该是公共的和虚拟的,或者是受保护的和非虚拟的。

啊,所以我想我必须在Base. 但这将取消自动生成的移动功能!

这里有什么干净的出路?

0 投票
1 回答
3252 浏览

c++ - 零混淆规则?

所以我一直在阅读零规则

简化版:我不明白这条规则的目的。三五法则是一种“经验法则”,但我看不到“经验法则”或该规则的任何其他具体意图。

详细版本:

让我引用:

具有自定义析构函数、复制/移动构造函数或复制/移动赋值运算符的类应该专门处理所有权。其他类不应具有自定义析构函数、复制/移动构造函数或复制/移动赋值运算符。

这是什么意思?他们所说的所有权是什么意思,所有权是什么?他们还展示了一个示例代码(我猜它与介绍有关):

他们想用这个展示什么,我真的迷失了这个。

此外,他们还讨论了当您处理多态类并且析构函数被声明为公共和虚拟以及该块隐式移动的事实时的场景。因此,您必须将它们全部声明为默认值:

这是否意味着当你有一个基类的析构函数被声明为 public 和 virtual 时,你真的必须将所有其他特殊成员函数声明为默认值吗?如果是这样,我不明白为什么。

我知道这在一个地方有很多混乱。