Answers:
这意味着您要使用该函数的编译器生成版本,因此无需指定主体。
您还可以= delete
用于指定您不希望编译器自动生成该函数。
随着移动构造函数和移动赋值运算符的引入,生成自动版本的构造函数,析构函数和赋值运算符的规则变得非常复杂。使用= default
和= delete
使事情变得容易,因为您无需记住规则:您只需说出要发生的事情即可。
= delete
更强大:这意味着,尽管仍然参与重载解析,但禁止使用该功能。
这是C ++ 0x的一项新功能,可告诉编译器创建相应构造函数或赋值运算符的默认版本,即仅对每个成员执行复制或移动动作的版本。这很有用,因为移动构造函数并非总是默认生成的(例如,如果您有一个自定义析构函数),与复制构造函数(以及类似的赋值方法)不同,但是如果没有非平凡的东西要写,最好让编译器会处理它,而不是每次自己将其拼写出来。
还要注意,如果提供任何其他非默认构造函数,则不会生成默认构造函数。如果仍然需要默认的构造函数,则可以使用此语法让编译器使用它。
作为另一个用例,在某些情况下不会隐式生成副本构造函数(例如,如果您提供自定义的移动构造函数)。如果仍然需要默认版本,则可以使用此语法进行请求。
有关详细信息,请参见标准的12.8节。
operator new/new[]
,operator delete/delete[]
和他们的过载。
C ++ 17 N4659标准草案
https://github.com/cplusplus/draft/blob/master/papers/n4659.pdf 11.4.2“显式默认函数”:
1形式的函数定义:
attribute-specifier-seq opt decl-specifier-seq opt declarator virt-specifier-seq opt = default ;
被称为显式默认定义。明确默认的功能应
(1.1)—是特殊的成员函数,
(1.2)—具有相同的声明函数类型(除了可能不同的ref限定符,以及对于复制构造函数或复制赋值运算符而言,参数类型可以为“对非常量T的引用”,其中T为成员函数的类的名称),就好像它已隐式声明一样,并且
(1.3)-没有默认参数。
2如果未隐式声明为constexpr,则未定义为delete的显式默认函数只能声明为constexpr。如果一个函数在其第一个声明中被显式默认,则如果隐式声明是隐式的,则将其隐式视为constexpr。
3如果显式默认的函数用noexcept-specifier声明,该声明不产生与隐式声明(18.4)相同的异常规范,则
(3.1)—如果该函数在其第一个声明中被显式默认,则将其定义为delete;
(3.2)—否则,程序格式错误。
4 [示例:
struct S { constexpr S() = default; // ill-formed: implicit S() is not constexpr S(int a = 0) = default; // ill-formed: default argument void operator=(const S&) = default; // ill-formed: non-matching return type ~ S() noexcept(false) = default; // deleted: exception specification does not match private: int i; // OK: private copy constructor S(S&); }; S::S(S&) = default; // OK: defines copy constructor
—结束示例]
5显式默认函数和隐式声明函数统称为默认函数,实现应为其提供隐式定义(15.1 15.4、15.8),这可能意味着将它们定义为已删除。如果函数是由用户声明的,并且未在其第一个声明中显式默认或删除,则由用户提供。由用户提供的显式默认函数(即,在第一次声明后显式默认)在显式默认的位置定义;如果将此类函数隐式定义为Delete,则程序格式错误。[注意:在第一个声明之后将函数声明为默认函数可以提供有效的执行和简洁的定义,同时还可以为不断发展的代码库提供稳定的二进制接口。—尾注]
6 [示例:
struct trivial { trivial() = default; trivial(const trivial&) = default; trivial(trivial&&) = default; trivial& operator=(const trivial&) = default; trivial& operator=(trivial&&) = default; ~ trivial() = default; }; struct nontrivial1 { nontrivial1(); }; nontrivial1::nontrivial1() = default; // not first declaration
—结束示例]
然后的问题是,当然可以隐式声明哪些函数以及何时隐式声明,我已在以下文章中进行了解释: