【问题标题】:Why would you "default" a copy/move constructor or a destructor?为什么要“默认”复制/移动构造函数或析构函数?
【发布时间】:2011-04-17 19:55:17
【问题描述】:

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 或析构函数?无论如何,隐式生成的实现不会做同样的事情吗?

【问题讨论】:

  • 您发布了一个问题,链接了您自己的重复问题,然后回答了您自己的问题?
  • @John:我撰写了问题和答案(正如 SO 不时鼓励的那样),因为我自己发现了这一点(其他人在 IRC 上提出了这个问题,我在上面详细说明了)。我在发布一个多小时后找到了副本——在我开始写这篇文章大约 4 小时后。 (不,总共没花那么长时间,我没有直接完成。;)
  • IRC 在哪里讨论 C++0x? (不过如果你不回答这个问题,我的工作效率可能会更好)
  • @James:哈! Freenode ##c++(在其他频道中,肯定包括##iso-c++,尽管前者的主题更广泛)和 EFnet #c++(主题差异很大)。

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


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    非公开

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

    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:基类析构函数应该是公共的和虚拟的,或者是受保护的和非虚拟的。

    定义控制

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

    【讨论】:

    • 你知道不允许非公开默认定义的理由是什么吗?
    • @James:我自己也想知道,但我看不出原因。最新的 WD N3126 也有同样的要求。不过,它与类定义中定义的默认函数是一致的,就像它们隐式声明的对应物一样。 (甚至 WRT 内联,因为在这种情况下前者是在类定义中定义的。)但是,我注意到 8.4.2/2 说“在其第一个声明中”,它必须在类定义中(对吗?),这似乎一种奇怪的表达方式。
    • @Roger:我确实需要学习如何阅读问题似乎与 answer略有不同 :)
    猜你喜欢
    • 2022-01-09
    • 2017-01-10
    • 1970-01-01
    • 2021-12-12
    • 2013-03-16
    • 1970-01-01
    • 2014-04-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多