可能重复:
C++ 11中默认函数的重点是什么?
C++ 11引入了默认方法(例如void myMethod() = default;).
它对方法有什么作用(方法在default编辑后如何表现).我该如何正确使用它们(它的用途是什么)?
有许多类成员被 C++ 标准视为“特殊成员函数”。这些都是:
这些成员函数很特殊,因为语言在类型上使用它们做了特殊的事情。它们的另一个特殊之处是,如果您不这样做,编译器可以为它们提供定义。这些是您可以使用该语法的唯一函数= 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)