“默认”是什么意思?意思是下课后函数声明?

发布于 2024-11-17 06:17:56 字数 266 浏览 3 评论 0原文

我见过在类中的函数声明旁边使用 default 。它有什么作用?

class C {
  C(const C&) = default;
  C(C&&) = default;
  C& operator=(const C&) & = default;
  C& operator=(C&&) & = default;
  virtual ~C() { }
};

I've seen default used next to function declarations in a class. What does it do?

class C {
  C(const C&) = default;
  C(C&&) = default;
  C& operator=(const C&) & = default;
  C& operator=(C&&) & = default;
  virtual ~C() { }
};

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

微暖i 2024-11-24 06:17:56

这是新的 C++11 功能

这意味着您想要使用该函数的编译器生成的版本,因此不需要指定函数体。

您还可以使用 = delete 来指定您希望编译器自动生成该函数。

随着移动构造函数和移动赋值运算符的引入,何时生成构造函数、析构函数和赋值运算符的自动版本的规则变得相当复杂。使用 =default=delete 使事情变得更容易,因为您不需要记住规则:您只需说出您想要发生的事情即可。

It's a new C++11 feature.

It means that you want to use the compiler-generated version of that function, so you don't need to specify a body.

You can also use = delete to specify that you don't want the compiler to generate that function automatically.

With the introduction of move constructors and move assignment operators, the rules for when automatic versions of constructors, destructors and assignment operators are generated has become quite complex. Using = default and = delete makes things easier as you don't need to remember the rules: you just say what you want to happen.

傲世九天 2024-11-24 06:17:56

这是一项新的 C++0x 功能,它告诉编译器创建相应构造函数或赋值运算符的默认版本,即仅对每个成员执行复制或移动操作的版本。这很有用,因为移动构造函数并不总是默认生成(例如,如果您有自定义析构函数),这与复制构造函数(以及同样的赋值)不同,但如果没有什么重要的东西需要编写,最好让编译器处理它而不是每次都自己拼写出来。

另请注意,如果您提供任何其他非默认构造函数,则不会生成默认构造函数。如果您仍然需要默认构造函数,则可以使用此语法让编译器创建一个。

作为另一个用例,有几种情况不会隐式生成复制构造函数(例如,如果您提供自定义移动构造函数)。如果您仍然想要默认版本,可以使用此语法请求它。

详细信息请参见标准第 12.8 节。

This is a new C++0x feature that tells the compiler to create the default version of the respective constructor or assignment operator, i.e. the one which just performs the copy or move action for each member. This is useful because the move constructor isn't always generated by default (e.g. if you have a custom destructor), unlike the copy constructor (and likewise for assignment), but if there's nothing non-trivial to write, it's better to let the compiler handle it than to spell it out yourself each time.

Also notice that a default constructor would not be generated if you provide any other non-default constructor. If you still want the default constructor, too, you can use this syntax to have the compiler make one.

As another use case, there are several situations in which a copy constructor would not be generated implicitly (e.g. if you provide a custom move constructor). If you still want the default version, you can request it with this syntax.

See Section 12.8 of the standard for details.

悲凉≈ 2024-11-24 06:17:56

这是 C++11 中的新增功能,请参阅此处。如果您已经定义了一个构造函数,但想要对其他构造函数使用默认值,那么它会非常有用。在 C++11 之前,一旦定义了一个构造函数,就必须定义所有构造函数,即使它们与默认值等效。

另请注意,在某些情况下,不可能提供用户定义的默认构造函数,该构造函数的行为与编译器在默认初始化下合成的构造函数相同。 default 允许您恢复该行为。

It is new in C++11, see here. It can be quite useful if you have defined one constructor, but want to use defaults for the others. Pre-C++11 you'd have to define all constructors once you have defined one, even if they are equivalent to the defaults.

Also note that in certain situations it is impossible to provide a user defined default constructor that behaves the same as the compiler synthesized one under both default and value initialization. default allows you to get that behaviour back.

野侃 2024-11-24 06:17:56

我在这些答案中没有看到的另一个用例是它可以轻松地允许您更改构造函数的可见性。例如,也许您希望一个友元类能够访问复制构造函数,但您不希望它公开可用。

Another use case that I do not see mentioned in these answers is that it easily allows you to change the visibility of a constructor. For example, maybe you want a friend class to be able to access the copy constructor, but you don't want it to be publicly available.

南城旧梦 2024-11-24 06:17:56

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 声明符 virt-specifier-seq opt = default ;

称为显式默认定义。明确默认的函数应

  • (1.1) — 是一个特殊的成员函数,

  • (1.2) — 具有相同的声明函数类型(除了可能不同的引用限定符以及除了
    对于复制构造函数或复制赋值运算符,参数类型可以是“引用
    non-const T”,其中 T 是成员函数的类的名称),就好像它已被隐式声明一样,

  • (1.3) — 没有默认参数。

2 未定义为已删除的显式默认函数只有在以下情况下才可以声明为 constexpr
已被隐式声明为 constexpr。如果函数在其第一个声明中显式默认,则它是
如果隐式声明是,则隐式地认为是 constexpr。

3 如果使用 noexcept 说明符声明显式默认的函数,则该函数不会产生相同的结果
异常规范作为隐式声明(18.4),那么

  • (3.1) — 如果函数在其第一个声明中显式默认,则将其定义为已删除;

  • (3.2) — 否则,程序格式错误。

4
[示例:

<前><代码>结构S {
constexpr S() = 默认值; // 格式错误:隐式 S() 不是 constexpr
S(int a = 0) = 默认值; // 格式错误:默认参数
void 运算符=(const S&) = 默认值; // 格式错误:返回类型不匹配
〜S()noexcept(假)=默认; // 删除:异常规范不匹配
私人的:
整数我; // OK:私有复制构造函数
S(S&);
};
S::S(S&) = 默认值; // OK: 定义复制构造函数

—结束示例]

5 显式默认函数和隐式声明函数统称为默认函数,并且
实现应为它们提供隐式定义(15.1 15.4,15.8),这可能意味着定义
它们已被删除。如果函数是用户声明的且未显式默认或删除,则该函数是用户提供的
在其第一次声明中。用户提供的显式默认函数(即,在其第一个函数之后显式默认)
声明)是在显式默认的位置定义的;如果这样的函数隐式定义为
删除后,程序格式错误。 [ 注意:在第一次声明后将函数声明为默认函数可以
提供高效的执行和简洁的定义,同时为不断发展的代码提供稳定的二进制接口
根据。 ——尾注]

6 [示例:

结构琐碎{
  微不足道的()=默认;
  琐碎(常量琐碎&)=默认;
  琐碎(琐碎&&)=默认;
  微不足道的&运算符=(const trivial&)=默认值;
  微不足道的&运算符=(琐碎&&)=默认;
  〜琐碎()=默认;
};
结构非平凡1 {
  非平凡1();
};
nontrivial1::nontrivial1() = 默认; // 不是第一个声明

—结束示例]

那么问题当然是哪些函数可以隐式声明以及何时发生,我已在以下位置解释过:

C++17 N4659 standard draft

https://github.com/cplusplus/draft/blob/master/papers/n4659.pdf 11.4.2 "Explicitly-defaulted functions":

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 ]

Then the question is of course which functions can be implicitly declared and when does that happen, which I have explained at:

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文