问题标签 [rule-of-five]

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 投票
2 回答
1421 浏览

c++ - CppCoreGuidelines C.21 是否正确?

在阅读 Bjarne Stroustrup 的 CoreCppGuidelines 时,我发现了一个与我的经验相矛盾的指南。

C.21需要以下内容:

如果您定义或=delete任何默认操作,请定义或=delete全部

原因如下:

特殊函数的语义密切相关,因此如果需要非默认,则很可能其他函数也需要修改。

根据我的经验,重定义默认操作最常见的两种情况如下:

#1:使用默认主体定义虚拟析构函数以允许继承:

#2:定义默认构造函数,对 RAII 类型的成员进行一些初始化:

根据我的经验,所有其他情况都很少见。

你怎么看这些例子?它们是 C.21 规则的例外,还是最好在此处定义所有默认操作?还有其他常见的例外吗?

0 投票
3 回答
424 浏览

c++ - 智能指针如何影响 5 规则?

我了解到,当您在类中使用指针时,您应该实现规则 5。如果您不使用指针,那么您可以,实际上更可取的是使用默认值。但是,这如何与智能指针一起使用?例如,包含 的类int*可能如下所示:

但是如果我们使用智能指针,这样做就足够了吗?

0 投票
1 回答
462 浏览

c++ - C++ 中 BST 类的五规则

我正在实现一个二叉搜索树类,并且想知道我的移动/复制构造函数和赋值运算符是否正确实现。(它似乎工作正常,但这是我第一次实现这些构造函数和赋值运算符,我怕我可能错过了一些东西。)

这是代码(也在在线编译器中):编辑:这是基于@Alex Larionov 评论的更新代码:

0 投票
0 回答
111 浏览

c++ - 基类虚拟析构函数——五法则?

我有一个State带有虚拟默认析构函数的基接口类。

然后是一些继承自它的类:

如果用户没有定义复制操作或析构函数,编译器会生成默认的移动操作。如果没有用户定义的移动操作,编译器会生成默认的复制操作。

  1. 我是否通过声明虚拟默认析构函数来纠正我已经有效地删除了默认移动操作?

  2. 如果基类隐式删除了它的移动操作,并且基类只是一个没有数据成员的接口,那么移动操作是否适用于派生类?

  3. 在这里遵循 5 规则真的明智吗?显式删除或默认所有 5 个特殊成员函数似乎相当臃肿。

0 投票
1 回答
157 浏览

c++ - 为什么具有显式声明的移动构造函数的类会失败`std::is_move_constructible_v`?

由于各种内部原因,我正在使用的库要求与其模板一起使用的类是可移动的和可分配的。我写了一个类,并给它一个显式的移动构造函数。

但是,这些静态断言中的第一个失败了:

我错过了什么?这真是令人费解,我在网上找不到任何关于为什么具有显式声明的移动构造函数的类可能无法移动构造的任何信息。是因为它是一个抽象类吗?任何帮助将不胜感激。

0 投票
2 回答
79 浏览

c++ - 带有在堆上分配的元素的 std::vector - 我需要 5 规则吗?

如果我的班级成员是这样的:

我是否需要编写五规则函数,还是 std::vector 会负责深度复制和删除堆上分配的元素?

编辑:以下代码使用默认的复制构造函数,所以我假设在我将 my_class1 对象复制到 my_class2 对象后,my_class1.my_vector 和 my_class2.my_vector 的元素将是相同的,因为复制了 MyStruct 指针,而不是数据本身. 但是,输出显示它们并不相同。您可以在此处运行代码:https ://onlinegdb.com/S1pK9YE4v

EDIT2:我知道智能指针。我特别感兴趣如果我使用原始指针会发生什么。

0 投票
1 回答
102 浏览

c++ - 用“= default”声明复制构造函数或根本不声明它有什么区别?

我试图了解各种功能的自动生成编译器代码的行为,例如:

  1. 析构函数
  2. 复制构造函数
  3. 赋值运算符
  4. 移动构造函数
  5. 移动赋值运算符

与未声明的情况相比,使用“= default”声明它们会导致任何功能差异吗?这个问题的答案在上面列出的函数中是否有所不同?如果没有功能差异,使用这两种情况的后果是什么?

使用“= default”声明的复制构造函数

未声明复制构造函数:

0 投票
2 回答
496 浏览

c++ - 在 C++ 中定义接口(没有成员的抽象类)

接口(C# 术语)是指没有数据成员的抽象类。因此,这样的类只指定了子类必须实现的契约(一组方法)。我的问题是:如何在现代 C++ 中正确实现这样的类?

C++ 核心指南 [1] 鼓励使用没有数据成员的抽象类作为接口 [I.25 和 C.121]。接口通常应该完全由公共纯虚函数和默认/空虚析构函数[来自 C.121] 组成。因此我想它应该用struct关键字声明,因为它只包含公共成员。

为了通过指向抽象类的指针来使用和删除子类对象,抽象类需要一个公共的默认虚拟析构函数[C.127]。“多态类应该禁止复制”[C.67] 通过删除复制操作(复制赋值运算符、复制构造函数)来防止切片。我假设这也扩展到移动构造函数和移动赋值运算符,因为它们也可以用于切片。对于实际的克隆,抽象类可以定义一个虚clone方法。(目前尚不完全清楚应该如何完成。通过智能指针或owner<T*>指南支持库。使用的方法owner<T>对我来说毫无意义,因为示例不应该编译:派生函数仍然没有override任何作用!?)。

在 C.129 中,该示例仅使用具有虚拟继承的接口。如果我理解正确,那么使用class Impl : public Interface {...};or派生接口(也许更好:“实现”?)没有区别class Impl : public virtual Interface {...};,因为它们没有可以复制的数据。接口不存在菱形问题(和相关问题)(我认为,这是诸如 C# 之类的语言不允许/需要类的多重继承的原因)。这里的虚拟继承是为了清楚起见吗?这是好习惯吗?

总之,似乎: 一个接口应该只包含公共方法。它应该声明一个公共的默认虚拟析构函数。它应该明确删除复制分配、复制构造、移动分配和移动构造。它可以定义一个多态克隆方法。我应该使用public virtual.

还有一件事让我感到困惑:一个明显的矛盾:“抽象类通常不需要构造函数”[C.126]。但是,如果通过删除所有复制操作(遵循 [C.67])来实现五规则,则该类不再具有默认构造函数。因此子类永远不能被实例化(因为子类构造函数调用基类构造函数),因此抽象基类总是需要声明一个默认构造函数?!我是不是误会了什么?

下面是一个例子。您是否同意这种方式来定义和使用没有成员(接口)的抽象类?

0 投票
0 回答
97 浏览

c++ - 使用多态性时的五法则

在使用接口(无论如何都是概念)和抽象类并努力理解规则如何工作时,我试图了解五规则。

假设我有这样的布局:

在其他一些代码中,我有一个充满 IEventInterface 的向量,例如std::vector<std::unique_ptr<IEventInterface>> m_events;

执行五律规则的正确地点在哪里?由于EventToday该类需要为某些清理定义的析构函数,因此它们需要启动,但我不确定在哪里?在上面的示例中,我将它们放在接口类中,但我怀疑这是错误的,因为接口或抽象类中的任何复制/移动/析构函数都不需要定义或删除。

0 投票
1 回答
69 浏览

c++ - 为无复制/无移动类型扩展的最小类是什么?

假设我想创建一些类来管理不应复制或移动的资源,这将是扩展和避免错误的最小类?

这个想法是,通过扩展类,我在0/3/5 规则的安全方面结束。

我有这个想法,这显然有效。