7

C++0x 允许您将某些函数指定为默认值:

struct A {
  A() = default;          // default ctor
  A(A const&) = default;  // copy ctor
  A(A&&) = default;       // move ctor
  A(Other);               // other ctor

  ~A() = default;         // dtor

  A& operator=(A const&) = default; // copy assignment
  A& operator=(A&&) = default;      // move assignment
};

这些函数的实现就像编译器生成它们一样,在大多数情况下,当您没有声明自己的函数时,通常会发生这种情况。

如果您声明任何 ctor(上述任何其他 ctor),则不会生成默认 ctor ,因此您可能需要将其默认为“将其恢复”。

但是,除非基成员或数据成员排除它们,否则类始终具有复制和移动 ctor⁠—⁠如果它们被排除,则默认实现将不起作用。一个类总是有一个 dtor。

为什么需要显式默认复制 ctor、移动 ctor 或析构函数?无论如何,隐式生成的实现不会做同样的事情吗?

4

2 回答 2

11

您可能需要这样做以将其访问权限更改为非公开或控制哪个翻译单元定义它们。

非公开

尽管这些函数通常是公开的,但您可能希望它们是非公开的,同时仍希望使用默认实现:

struct A {
protected:
  ~A();

private:
  A();
  A(A const&);
  A(A&&);
};

// according to N3092, §8.4.2/2, cannot be non-public and defaulted
// in the class definition
A::~A() = default;
A::A() = default;
A::A(A const&) = default;
A::A(A&&) = default;

此类可以默认构造、复制和移动,但只能由 A 的方法和朋友进行。这对于可能更严格控制构造的工厂很有用。

受保护的析构函数是基类的公共虚拟/受保护非虚拟指南的后半部分:

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

清晰度控制

此外,默认函数可用于维护稳定的二进制接口,因为您可以控制默认函数的定义位置。默认并不意味着内联,因为隐式声明的版本将是。(在上面的代码中,默认函数不能在标头中或添加了 inline 说明符。)

于 2010-09-27T14:57:30.180 回答
2

除了功能目的之外,我发现它对清晰很有用。它清楚地表明该结构是默认可构造的(或其他),并且我们正在使用编译器生成的行为。对代码进行自我记录越多越好。

于 2010-09-27T15:35:35.250 回答