类成员初始化的首选方法? [英] Preferred way of class member initialization?
问题描述
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{}
performs list initialization which- becomes value initialization if
{}
is empty, or could be aggregate initialization ifA
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 ifA
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 ofa
.正确。
- 默认构造函数'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. StatementB b;
for this example will call the default constructor, but leaves indeterminate values ofA
'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()
是构造函数初始化器和a()
是一个成员初始化器成员初始值设定器列表的一部分。 - 使用直接初始化
()
或者,如果()
为空,值初始化。 - 不希望使用聚合初始化。
- 不会警告缩小转换。
: a()
is a constructor initializer anda()
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 现在有非静态数据成员初始值设定,如果您需要,可能需要一个构造函数来初始化它使用聚合初始化和编译器不完全符合C ++ 14标准。
- 成员初始化程序使用列表初始化
{}
其中 - 可以成为值初始化如果
{}
为空或聚合初始化如果A
是聚合。 - 如果
a
是唯一的成员,那么不必定义默认构造函数,并且默认构造函数将被隐式定义。 / li>
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 ifA
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 forstd::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 forstd::vector<int> v1(5,10)
andstd::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 becausestd::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:
- 直接初始化
a()
成为值初始化,如果()
为空。 - 列出初始化 a>
a {}
,也会成为值初始化如果{}
为空。
- 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屋!
- uses value initialization if
- This is copy initialization where a prvalue temporary is constructed with list initialization
- uses value initialization if the
- This is copy initialization where a prvalue temporary is constructed with direct initialization