为什么要“默认”复制/移动构造函数或析构函数?

时间:2010-09-27 14:56:45

标签: c++ c++11 defaulted-functions

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 生成,因此您可能需要将其默认为“将其恢复原状。”

但是,除非基类或数据成员排除它们,否则类总是有一个副本并移动它们 - 如果它们被排除,则默认实现将不起作用。一个班级总是有一个dtor。

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

2 个答案:

答案 0 :(得分: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的方法和朋友。这对于工厂可能受到更严格控制的工厂非常有用。

受保护的析构函数是基类的public-virtual/protected-nonvirtual guideline的后半部分:

  

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

定义控制

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

答案 1 :(得分:2)

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