什么是默认方法以及如何正确使用它们?

Mar*_*cia 10 c++ c++11

可能重复:
C++ 11中默认函数的重点是什么?

C++ 11引入了默认方法(例如void myMethod() = default;).

它对方法有什么作用(方法在default编辑后如何表现).我该如何正确使用它们(它的用途是什么)?

Nic*_*las 4

有许多类成员被 C++ 标准视为“特殊成员函数”。这些都是:

  • 默认构造函数(可以不带参数调用的构造函数)。
  • 复制构造函数(一种可以使用一个参数来调用的构造函数,该参数是作为左值引用的对象类型)。
  • 复制赋值运算符(一种operator=重载,可以使用一个参数来调用,该参数是作为左值引用或值的对象类型)。
  • 移动构造函数(一种可以使用一个参数调用的构造函数,该参数是作为右值引用的对象类型)。
  • 移动赋值运算符(一种operator=重载,可以使用一个作为右值引用或值的对象类型参数进行调用)。
  • 析构函数。

这些成员函数很特殊,因为语言在类型上使用它们做了特殊的事情。它们的另一个特殊之处是,如果您不这样做,编译器可以为它们提供定义。这些是您可以使用该语法的唯一函数= default;

问题是编译器只会在某些条件下提供定义。也就是说,在某些情况下将不提供定义。

我不会详细介绍整个列表,但其他人提到的一个例子。如果您为不是特殊构造函数的类型提供构造函数(即:不是上面提到的构造函数之一),则不会自动生成默认构造函数。因此,这种类型:

struct NoDefault
{
  NoDefault(float f);
};
Run Code Online (Sandbox Code Playgroud)

NoDefault不能默认构造。因此,它不能用在任何需要默认构造的上下文中。你不能NoDefault()创建一个临时的。您无法创建数组NoDefault(因为它们是默认构造的)。如果不提供要从中复制的值或任何其他需要类型的操作,则无法创建std::vector<NoDefault>并调用大小调整构造函数。DefaultConstructible

但是,您可以这样做:

struct UserDefault
{
  UserDefault() {}
  UserDefault(float f);
};
Run Code Online (Sandbox Code Playgroud)

那会解决一切,对吗?

错误的!

这和这个不是一回事:

struct StdDefault
{
  StdDefault() = default;
  StdDefault(float f);
};
Run Code Online (Sandbox Code Playgroud)

为什么?因为StdDefault琐碎的类型。这意味着什么?我不会解释整个事情,但请到这里了解详细信息。当您可以做到时,使类型变得简单通常是一个有用的功能。

普通类型的要求之一是它没有用户提供的默认构造函数。UserDefault有一个提供的,即使它与编译器生成的完全相同。因此,UserDefault这并不是一件小事。StdDefault是一个简单的类型,因为= default语法意味着编译器将生成它。所以它不是用户提供的。

语法= default告诉编译器,“无论如何都要生成这个函数,即使你通常不会生成。” 这对于确保类是普通类型非常重要,因为您实际上无法像编译器那样实现特殊成员。它允许您强制编译器生成该函数,即使它不会。

这在很多情况下都非常有用。例如:

class UniqueThing
{
public:
  UniqueThing() : m_ptr(new SomeType()) {}
  UniqueThing(const UniqueThing &ptr) : m_ptr(new SomeType(*ptr)) {}
  UniqueThing &operator =(const UniqueThing &ptr)
  {
    m_ptr.reset(new SomeType(*ptr)); return *this;
  }

private:
  std::unique_ptr<SomeType> m_ptr;
};
Run Code Online (Sandbox Code Playgroud)

我们必须编写每一个函数来使类复制 unique_ptr 的内容;没有办法避免这种情况。但我们也希望它是可移动的,并且移动构造函数/赋值运算符不会自动为我们生成。重新实现它们是愚蠢的(如果我们添加更多成员,则容易出错),因此我们可以使用以下= default语法:

class UniqueThing
{
public:
  UniqueThing() : m_ptr(new SomeType()) {}
  UniqueThing(const UniqueThing &ptr) : m_ptr(new SomeType(*ptr)) {}
  UniqueThing(UniqueThing &&ptr) = default;
  UniqueThing &operator =(const UniqueThing &ptr)
  {
    m_ptr.reset(new SomeType(*ptr)); return *this;
  }

  UniqueThing &operator =(UniqueThing &&ptr) = default;

private:
  std::unique_ptr<SomeType> m_ptr;
};
Run Code Online (Sandbox Code Playgroud)