1

为每个非用户定义的构造函数声明始终默认的构造函数的优缺点是什么?

考虑一个具有用户定义构造函数的类,它不需要其他用户定义构造函数,它将是:

class Foo
{
public:
   Foo() { // user-defined declaration }
   Foo(const Foo&) = default;
   Foo(Foo&&) noexcept = default;
   ~Foo() = default;

   Foo& operator=(const Foo&) = default;
   Foo& operator=(Foo&&) = default;
}

这样做还有其他实际的优点/缺点吗?

4

2 回答 2

5

我头顶的几个缺点:

  1. 您可以忘记特殊功能。您显示的示例未定义复制/移动赋值运算符。
  2. 在标头中将析构函数声明为默认值将使您无法在例如类的std::unique_ptr成员中使用前向声明的类。您可以通过包含类定义来缓解这种情况(导致非平凡项目的(重新)构建时间最终总体增加,尤其是当未转发声明的类经常更改时)。= default您可以通过将 移动到源文件中的定义来缓解这种情况。
  3. (主观的)它在视觉上重载了类定义:每个有能力的 C++ 开发人员都知道这些通常是自动生成的,因此它们没有提供额外的信息,尽管它们需要时间来阅读和理解。请注意,我只是在谈论“一切默认”的情况,因此不会删除任何特殊功能或类似的功能。
  4. 添加只移动数据成员将要求您还删除 =default 复制构造函数和赋值运算符。您是否希望这样做部分是风格问题,但这确实会导致更多涉及的代码更改,尤其是在更一般意义上重构此类类时。
  5. 如果任何其他特殊的编译器生成的函数被添加到更高版本的 C++ 中,您会自动错过它们,否则您已经隐式定义了它们。

可能还有更多,超越这些的微妙程度上升。

于 2018-04-19T07:06:37.640 回答
5

没有优势。它只是向您的代码的读者证明您不知道 C++ 编译器是如何工作的。如果您将此作为策略强制执行,您也容易受到未来 C++ 标准更改的影响。

一个例外是使用

virtual ~Foo() = default;

在一个基类中,我们引入了可以帮助内存管理的多态性。

另一类例外情况是您可能希望更改default功能函数的访问说明符:

protected:
    Foo foo() = default;

如果您只想通过继承使用类,但不想使其成为多态类型,我在此处给出的显式示例可能很有用。

于 2018-04-19T07:16:07.477 回答