类成员初始化的首选方法? [英] Preferred way of class member initialization?

查看:193
本文介绍了类成员初始化的首选方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

class A { public: int x[100]; };

声明 A a 不会初始化对象(要通过字段 x 中的无用值来查看)。
以下将触发初始化: A a {} auto a = A() auto a = A {}

Declaring A a will not initialize the object (to be seen by garbage values in the field x). The following will trigger initialization: A a{} or auto a = A() or auto a = A{}.

是否应优先考虑三者中的任何一个?

Should any particular one of the three be preferred?

接下来,让我们成为另一个类的成员:

Next, let us make it a member of another class:

class B { public: A a; };

B 的默认构造函数似乎保护 a 的初始化。
然而,如果使用自定义构造函数,我必须照顾它。
以下两个选项工作:

The default constructor of B appears to take care of initialization of a. However, if using a custom constructor, I have to take care of it. The following two options work:

class B { public: A a;  B() : a() { } };

或:

class B { public: A a{};  B() { } };

是否应优先选择两者中的任何一个?

Should any particular one of the two be preferred?

推荐答案

初始化



Initialization


class A { public: int x[100]; };

声明 A a 不会初始化对象(在字段x中被垃圾
值看到)。

Declaring A a will not initialize the object (to be seen by garbage values in the field x).

正确 A a 未经初始化程序定义,且不符合默认值的任何要求初始化

Correct A a is defined without an initializer and does not fulfill any of the requirements for default initialization.


1)以下内容将触发初始化:

1) The following will trigger initialization:

A a{};


是;


  • a {} 执行列表初始化

  • 成为值初始化如果 {} 为空,或者可以聚合初始化如果 A 是聚合。

  • 如果默认构造函数被删除。例如 A()= delete; (如果'A'仍被视为汇总)

  • 会警告缩小转换。 >
  • a{} performs list initialization which
  • becomes value initialization if {} is empty, or could be aggregate initialization if A is an aggregate.
  • Works even if the default constructor is deleted. e.g. A() = delete; (If 'A' is still considered an aggregate)
  • Will warn of narrowing conversion.

2)以下内容将触发初始化:

2) The following will trigger initialization:

auto a = A();



  • 这是复制初始化,其中通过直接初始化 () which

    • This is copy initialization where a prvalue temporary is constructed with direct initialization () which
      • uses value initialization if the () is empty.
      • No hope of aggregate initialization.

      • 允许跳过复制/移动构造函数的副作用。


      3)以下将触发初始化:

      3) The following will trigger initialization:

      auto a = A{}
      


      是;


      • 这是复制初始化,其中通过列表初始化构造临时prvalue {} 其中

        • This is copy initialization where a prvalue temporary is constructed with list initialization {} which
          • uses value initialization if {} is empty, or could be aggregate initialization if A is an aggregate.
          • The prvalue temporary is then used to direct-initialize the object.

          • 允许跳过复制/移动构造函数的副作用。


          是否应优先选择三种特定的一种?

          Should any particular one of the three be preferred?

          $ c> A a {} 。

          Clearly you should prefer A a{}.


          接下来,让我们成为另一个类的成员:

          Next, let us make it a member of another class:

          class B { public: A a; };
          

          B 的默认构造函数似乎保护初始化
          a

          The default constructor of B appears to take care of initialization of a.

          正确。


          • 默认构造函数'B'将调用 A ,但不会初始化成员。不会触发直接或列表初始化。语句 B b; 对于这个例子将调用默认构造函数,但留下 A 的数组的不确定值。 / li>
          • the implicitly-defined default constructor of 'B' will call the default constructor of A, but will not initialize the members. No direct or list initialization will be triggered. Statement B b; for this example will call the default constructor, but leaves indeterminate values of A's array.

          1)但是,如果使用自定义构造函数,
          以下两个选项工作:

          1) However, if using a custom constructor, I have to take care of it. The following two options work:

          class B { public: A a;  B() : a() { } };
          


          • : a() is a constructor initializer and a() is a member initializer as part of the member initializer list.
          • Uses direct initialization () or, if () is empty, value initialization.
          • No hope of using aggregate initialization.
          • Will not warn of narrowing conversion.

          2)或:

          2) or:

          class B { public: A a{};  B() { } };
          


          • a now has a non-static data member initializer, which may require a constructor to initialize it if you are using aggregate initialization and the compiler is not fully C++14 compliant.
          • The member initializer uses list initialization {} which
          • may become either value initialization if {} is empty or aggregate initialization if A is an aggregate.
          • If a is the only member then the default constructor does not have to be defined and the default constructor will be implicitly defined.

          显然您应该选择第二个选项。

          Clearly you should prefer the second option.

          就我个人而言,我喜欢使用大括号,一些例外用于 auto 以及构造函数可能会将其误认为 std :: initializer_list

          Personally, I prefer using braces everywhere, with some exceptions for auto and cases where a constructor could mistake it for std::initializer_list:

          class B { public: A a{}; };
          

          A std :: vector 不同于 std :: vector< int> v1(5,10) std :: vector< int> v1 {5,10} (5,10)你会得到5个元素,每个值为10,但 {5,10} 你得到两个元素分别包含5和10,因为 std :: initializer_list 是强烈推荐,如果你使用大括号。

          A std::vector constructor will behave differently for std::vector<int> v1(5,10) and std::vector<int> v1{5,10}. with (5,10) you get 5 elements with the value 10 in each one, but with {5,10} you get two elements containing 5 and 10 respectively because std::initializer_list is strongly preferred if you use braces. This is explained very nicely in item 7 of Effective Modern C++ by Scott Meyers.

          成员初始值列表,可以考虑两种格式:

          Specifically for member initializer lists, two formats may be considered:

          • Direct initialization a() which becomes value initialization if the () is empty.
          • List initialization a{} which also becomes value initialization if {} is empty.

          初始化列表,幸运的是,没有最烦躁的解析的风险。在初始化列表之外,作为一个语句, A a()将声明一个函数与 A a {} 这将是明确的。此外,列表初始化有助于防止缩小转化。

          In member initializer lists, fortunately, there is no risk of the most vexing parse. Outside of the initializer list, as a statement on its own, A a() would have declared a function vs. A a{} which would have been clear. Also, list initialization has the benefit of preventing narrowing conversions.

          所以,总而言之,这个问题的答案是,它取决于你想要确定什么,这将决定你选择的形式。对于空初始化器,规则更宽容。

          So, in summary the answer to this question is that it depends on what you want to be sure of and that will determine the form you select. For empty initializers the rules are more forgiving.

          这篇关于类成员初始化的首选方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆