总是声明违约构造函数的优点和缺点是什么?

时间:2018-04-19 06:59:32

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

为每个非用户定义的构造函数声明始终默认的构造函数有什么利弊?

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

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;
}

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

2 个答案:

答案 0 :(得分:5)

我头顶的几个缺点:

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

答案 1 :(得分:5)

没有任何优势。它只是向读者展示了您不知道C ++编译器如何工作的代码。如果将此强制实施为策略,则您也很容易受到未来C ++标准的更改。

使用

的例外情况
let addLeadingZero(v){
    return v < 10 ? ("0" + v) : v;
}
$scope.TravelTime = addLeadingZero(TravelTimeHoursDiff) + ':' + addLeadingZero(TravelTimeMinutesDiff);

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

另一类异常是您可能想要更改virtual ~Foo() = default; 能力函数的访问说明符的情况:

default

如果希望通过继承使用类,但不想使其成为多态类型,那么我在此提供的显式示例非常有用。