初始化
class A { public: int x[100]; };
声明A a
不会初始化该对象(被垃圾看到
x) 字段中的值。
Correct A a
定义时没有初始化程序,并且不满足以下任何要求默认初始化 http://en.cppreference.com/w/cpp/language/default_initialization.
1)以下将触发初始化:
A a{};
Yes;
-
a{}
施行列表初始化 http://en.cppreference.com/w/cpp/language/list_initialization which
- becomes 值初始化 http://en.cppreference.com/w/cpp/language/value_initialization if
{}
是空的,或者可以是聚合初始化 http://en.cppreference.com/w/cpp/language/aggregate_initialization if A
是一个聚合体。
- 即使默认构造函数被删除也能正常工作。例如
A() = delete;
(如果“A”仍被视为聚合)
- 将警告缩小转换范围。
2)以下将触发初始化:
auto a = A();
Yes;
- This is copy initialization http://en.cppreference.com/w/cpp/language/copy_initialization where a prvalue temporary is constructed with direct initialization http://en.cppreference.com/w/cpp/language/direct_initialization
()
which
- uses 值初始化 http://en.cppreference.com/w/cpp/language/value_initialization if the
()
是空的。
- 没有希望聚合初始化 http://en.cppreference.com/w/cpp/language/aggregate_initialization.
- 然后使用临时纯右值直接初始化 http://en.cppreference.com/w/cpp/language/direct_initialization物体。
-
Copy elision http://en.cppreference.com/w/cpp/language/copy_elision may be, and normally is employed, to optimize out the copy and construct
A
in place.
- 移动构造函数不能被删除。例如
A(A&&) = delete;
- 如果删除复制构造函数,则必须存在移动构造函数。例如
A(const A&) = delete; A(A&&) = default;
- 不会警告缩小转换。
3)以下将触发初始化:
auto a = A{}
Yes;
- This is copy initialization http://en.cppreference.com/w/cpp/language/copy_initialization where a prvalue temporary is constructed with list initialization http://en.cppreference.com/w/cpp/language/list_initialization
{}
which
- uses 值初始化 http://en.cppreference.com/w/cpp/language/value_initialization if
{}
为空,或者可以是聚合初始化,如果A
是一个聚合体。
- 然后使用临时纯右值直接初始化 http://en.cppreference.com/w/cpp/language/direct_initialization物体。
-
Copy elision http://en.cppreference.com/w/cpp/language/copy_elision may be, and normally is employed, to optimize out the copy and construct
A
in place.
- 移动构造函数不能被删除。例如
A(A&&) = delete;
- 如果删除复制构造函数,则必须存在移动构造函数。例如
A(const A&) = delete; A(A&&) = default;
- 将警告缩小转换范围。
- 即使默认构造函数被删除也能正常工作。例如
A() = delete;
(如果“A”仍被视为聚合)
应该优先选择三者中的哪一个吗?
显然你应该更喜欢A a{}
.
成员初始化
接下来,让我们让它成为另一个类的成员:
class B { public: A a; };
默认构造函数B
似乎负责初始化
的a
.
不,这是不正确的。
- the 隐式定义的'B' 的默认构造函数将调用
A
,但不会初始化成员。不会触发直接或列表初始化。陈述B b;
对于此示例将调用默认构造函数,但留下不确定的值A
的数组。
1)但是,如果使用自定义构造函数,我必须处理它。这
以下两个选项有效:
class B { public: A a; B() : a() { } };
这会起作用;
-
: a()
is a 构造函数初始值设定项 http://en.cppreference.com/w/cpp/language/function#Function_definition and a()
是成员初始值设定项作为一部分成员初始值设定项列表 http://en.cppreference.com/w/cpp/language/initializer_list.
- Uses 直接初始化 http://en.cppreference.com/w/cpp/language/direct_initialization
()
or, if ()
是空的,值初始化 http://en.cppreference.com/w/cpp/language/value_initialization.
- 不希望使用聚合初始化。
- 不会警告缩小转换。
2) or:
class B { public: A a{}; B() { } };
这会起作用;
-
a
现在有一个非静态数据成员初始值设定项 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3653.html,如果您使用聚合初始化并且编译器是,则可能需要构造函数来初始化它不完全符合 C++14 https://blogs.msdn.microsoft.com/vcblog/2014/11/17/c111417-features-in-vs-2015-preview/.
- 成员初始值设定项使用列表初始化 http://en.cppreference.com/w/cpp/language/list_initialization
{}
which
- 可能会变成值初始化 http://en.cppreference.com/w/cpp/language/value_initialization if
{}
为空或聚合初始化 http://en.cppreference.com/w/cpp/language/aggregate_initialization if A
是一个聚合体。
- If
a
是唯一的成员,则不必定义默认构造函数,并且默认构造函数将被隐式定义。
显然你应该更喜欢第二种选择。
就我个人而言,我更喜欢在任何地方使用大括号,一些例外 https://stackoverflow.com/a/18222927/1460794 for auto
以及构造函数可能将其误认为的情况std::initializer_list
:
class B { public: A a{}; };
A std::vector
构造函数的行为会有所不同std::vector<int> v1(5,10)
and std::vector<int> v1{5,10}
. with (5,10)
你得到 5 个元素,每个元素的值为 10,但是{5,10}
你会得到两个分别包含 5 和 10 的元素,因为std::initializer_list
如果您使用大括号,则强烈推荐。 Scott Meyers 的《Effective Modern C++》第 7 条对此进行了很好的解释。
专门针对成员初始值设定项列表 http://en.cppreference.com/w/cpp/language/initializer_list,可以考虑两种格式:
-
直接初始化 http://en.cppreference.com/w/cpp/language/direct_initialization
a()
这变成值初始化 http://en.cppreference.com/w/cpp/language/value_initialization if the ()
是空的。
-
列表初始化 http://en.cppreference.com/w/cpp/language/list_initialization
a{}
这也成为值初始化 http://en.cppreference.com/w/cpp/language/value_initialization if {}
是空的。
幸运的是,在成员初始值设定项列表中,不存在最令人烦恼的解析的风险。在初始化列表之外,作为一个单独的语句,A a()
会声明一个函数 vs.A a{}
这本来就很清楚了。还,列表初始化 http://en.cppreference.com/w/cpp/language/list_initialization具有防止缩小转换的好处。
因此,总而言之,这个问题的答案是,这取决于您想要确定的内容,并且这将决定您选择的形式。对于空的初始化器,规则更加宽松。