Las*_*ann 5 initialization class-members c++11
class A { public: int x[100]; };
Run Code Online (Sandbox Code Playgroud)
声明A a不会初始化对象(由字段中的垃圾值看到x).以下将触发初始化:A a{}或auto a = A()或auto a = A{}.
这三个中的任何一个应该是首选吗?
接下来,让我们使它成为另一个类的成员:
class B { public: A a; };
Run Code Online (Sandbox Code Playgroud)
默认构造函数B似乎负责初始化a.但是,如果使用自定义构造函数,我必须处理它.以下两个选项有效:
class B { public: A a; B() : a() { } };
Run Code Online (Sandbox Code Playgroud)
要么:
class B { public: A a{}; B() { } };
Run Code Online (Sandbox Code Playgroud)
这两个中的任何一个都应该是首选吗?
Run Code Online (Sandbox Code Playgroud)class A { public: int x[100]; };声明
A a不会初始化对象(可以通过字段 x 中的垃圾值看到)。
CorrectA a是在没有初始化器的情况下定义的,并且不满足默认初始化的任何要求。
1)以下将触发初始化:
Run Code Online (Sandbox Code Playgroud)A a{};
是的;
a{}执行列表初始化{}AA() = delete;(如果“A”仍被视为聚合)2)以下将触发初始化:
Run Code Online (Sandbox Code Playgroud)auto a = A();
是的;
()构造的
A就地构建。
A(A&&) = delete;A(const A&) = delete; A(A&&) = default;3)以下将触发初始化:
Run Code Online (Sandbox Code Playgroud)auto a = A{}
是的;
{}构造的
A就地构建。
A(A&&) = delete;A(const A&) = delete; A(A&&) = default;A() = delete;(如果“A”仍被视为聚合)应该优先选择这三者中的哪一个?
显然你应该更喜欢A a{}.
接下来,让我们让它成为另一个类的成员:
Run Code Online (Sandbox Code Playgroud)class B { public: A a; };的默认构造函数
B似乎负责 的初始化a。
不,这是不正确的。
A,但不会初始化成员。不会触发直接或列表初始化。此示例的语句B b;将调用默认构造函数,但会留下 的A数组的不确定值。1)但是,如果使用自定义构造函数,我必须处理它。以下两个选项有效:
Run Code Online (Sandbox Code Playgroud)class B { public: A a; B() : a() { } };
这会起作用;
: a()是构造函数初始值设定项,并且a()是作为成员初始值设定项列表的一部分的成员初始值设定项。(),或者如果()为空,则使用值初始化。2) 或:
Run Code Online (Sandbox Code Playgroud)class B { public: A a{}; B() { } };
这会起作用;
a现在有一个非静态数据成员初始值设定项,如果您使用聚合初始化并且编译器不完全符合 C++14,则可能需要构造函数来初始化它。{}{}Aa是唯一的成员,则不必定义默认构造函数,并且将隐式定义默认构造函数。显然你应该更喜欢第二种选择。
就我个人而言,我更喜欢在任何地方使用大括号,但有一些例外和auto构造函数可能将其误认为的情况std::initializer_list:
class B { public: A a{}; };
Run Code Online (Sandbox Code Playgroud)
构造函数对于和 的std::vector行为会有所不同。你会得到 5 个元素,每个元素的值为 10,但你会得到两个分别包含 5 和 10 的元素,因为如果使用大括号,这是强烈推荐的。Scott Meyers 的《Effective Modern C++》第 7 条对此进行了很好的解释。std::vector<int> v1(5,10)std::vector<int> v1{5,10}(5,10){5,10}std::initializer_list
特别是对于成员初始值设定项列表,可以考虑两种格式:
幸运的是,在成员初始值设定项列表中,不存在最令人烦恼的解析的风险。在初始值设定项列表之外,作为其自身的语句,A a()将声明一个函数A a{},这将是明确的。另外,列表初始化还具有防止缩小转换范围的优点。
因此,总而言之,这个问题的答案是,这取决于您想要确定的内容,并且这将决定您选择的形式。对于空的初始化器,规则更加宽松。