我看到default
被用在类中函数声明的旁边。它是做什么用的?
class C {
C(const C&) = default;
C(C&&) = default;
C& operator=(const C&) & = default;
C& operator=(C&&) & = default;
virtual ~C() { }
};
我看到default
被用在类中函数声明的旁边。它是做什么用的?
class C {
C(const C&) = default;
C(C&&) = default;
C& operator=(const C&) & = default;
C& operator=(C&&) & = default;
virtual ~C() { }
};
这是一个C++11的新特性。
它意味着你想要使用编译器生成的函数版本,所以你不需要指定函数体。
你也可以使用= delete
来指定你不想要自动生成该函数。
随着移动构造函数和移动赋值操作符的引入,自动生成构造函数、析构函数和赋值操作符的规则变得非常复杂。使用=default
和=delete
可以使事情变得更容易,因为你不需要记住这些规则:你只需要说明你想发生什么。
= delete
更加严格:它意味着使用该函数是被禁止的,尽管它仍然参与重载决议。 - Deduplicator这是一个新的C++0x特性,它告诉编译器创建相应构造函数或赋值运算符的默认版本,即只为每个成员执行复制或移动操作。这很有用,因为移动构造函数并不总是默认生成的(例如,如果您有自定义析构函数),与复制构造函数不同(类似于赋值运算符)。但如果没有什么非常规的东西需要写,最好让编译器处理它,而不是每次都自己拼写。
同时请注意,如果您提供任何其他非默认构造函数,则不会生成默认构造函数。如果仍然需要默认构造函数,则可以使用此语法让编译器生成一个。
另一个用例是,在某些情况下不会隐式生成复制构造函数(例如,如果提供了自定义移动构造函数)。如果仍然需要默认版本,则可以使用此语法请求它。
详情请参见标准的第12.8节。
operator new/new[]
、operator delete/delete[]
及其重载。 - Sebastian Mach这是C++11中的新特性,详见这里。如果你定义了一个构造函数,但想要使用默认值来定义其他构造函数,则此功能可能非常有用。在C++11之前,一旦定义了一个构造函数,即使它们等同于默认值,也必须定义所有构造函数。
还要注意,在某些情况下,不可能提供用户定义的默认构造函数,使其在默认值初始化和值初始化下与编译器生成的构造函数表现相同。使用default
关键字可以让你重新获得这个行为。
这个用例在其他答案中似乎没有提到,它可以轻松地让您更改构造函数的可见性。例如,也许您希望友元类能够访问复制构造函数,但您不希望该构造函数公开可用。
C++17 N4659标准草案
https://github.com/cplusplus/draft/blob/master/papers/n4659.pdf 11.4.2 "显式默认函数":
然后问题当然是哪些函数可以被隐式声明,以及何时发生这种情况,我已经在以下链接中解释过了:1 A function definition of the form:
attribute-specifier-seq opt decl-specifier-seq opt declarator virt-specifier-seq opt = default ;
is called an explicitly-defaulted definition. A function that is explicitly defaulted shall
(1.1) — be a special member function,
(1.2) — have the same declared function type (except for possibly differing ref-qualifiers and except that in the case of a copy constructor or copy assignment operator, the parameter type may be “reference to non-const T”, where T is the name of the member function’s class) as if it had been implicitly declared, and
(1.3) — not have default arguments.
2 An explicitly-defaulted function that is not defined as deleted may be declared constexpr only if it would have been implicitly declared as constexpr. If a function is explicitly defaulted on its first declaration, it is implicitly considered to be constexpr if the implicit declaration would be.
3 If a function that is explicitly defaulted is declared with a noexcept-specifier that does not produce the same exception specification as the implicit declaration (18.4), then
(3.1) — if the function is explicitly defaulted on its first declaration, it is defined as deleted;
(3.2) — otherwise, the program is ill-formed.
4 [ Example:
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
— end example ]
5 Explicitly-defaulted functions and implicitly-declared functions are collectively called defaulted functions, and the implementation shall provide implicit definitions for them (15.1 15.4, 15.8), which might mean defining them as deleted. A function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration. A user-provided explicitly-defaulted function (i.e., explicitly defaulted after its first declaration) is defined at the point where it is explicitly defaulted; if such a function is implicitly defined as deleted, the program is ill-formed. [ Note: Declaring a function as defaulted after its first declaration can provide efficient execution and concise definition while enabling a stable binary interface to an evolving code base. — end note ]
6 [ Example:
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
— end example ]