Ahm*_*Ali 38 c++ initialization c++11
在C++ 11中初始化对象成员变量的这些方法有何不同?还有另外一种方法吗?哪种方式更好(性能)?:
class any {
public:
obj s = obj("value");
any(){}
};
Run Code Online (Sandbox Code Playgroud)
要么
class any {
public:
obj s;
any(): s("value"){}
};
Run Code Online (Sandbox Code Playgroud)
谢谢.
Pio*_*cki 44
不,这些都不一样.
它们之间的区别与适用于直接初始化与复制初始化的相同,这是微妙但通常非常混乱.
§12.6.2[class.base.init]:
的表达式列表或支撑-INIT列表在MEM-初始化用于初始化指定子对象(或者,在一个委派构造,完整的类对象的情况下)按照8.5的初始化规则直接初始化.[...]
在非委托构造函数中,如果给定的非静态数据成员或基类未由mem-initializer-id指定(包括没有mem-initializer-list的情况,因为构造函数没有ctor-initializer)然后,实体不是抽象类(10.4)的虚基类
- 如果实体是具有大括号或等于初始化程序的非静态数据成员,则按照8.5中的规定初始化该实体;
§8.5[dcl.init]:
在表单中发生的初始化
T x = a;
以及参数传递,函数返回,抛出异常(15.1),处理异常(15.3)和聚合成员初始化(8.5.1)称为复制初始化.
在member-initializer-list上初始化非静态数据成员遵循直接初始化的规则,该规则不会创建需要移动/复制的中间临时值(如果没有复制省略而编译),也不是数据成员必须是可复制/可移动的(即使复制被删除).此外,直接初始化引入了显式上下文,而复制初始化是非显式的(如果为初始化选择了构造函数explicit,则程序将无法编译).
换句话说,obj s = obj("value");如果obj声明为:语法将不会编译:
struct obj
{
obj(std::string) {}
obj(const obj&) = delete;
};
Run Code Online (Sandbox Code Playgroud)
要么:
struct obj
{
obj(std::string) {}
explicit obj(const obj&) {}
};
Run Code Online (Sandbox Code Playgroud)
作为一个更切实的例子,虽然下面不会编译:
struct any
{
std::atomic<int> a = std::atomic<int>(1); // ill-formed: non-copyable/non-movable
std::atomic<int> b = 2; // ill-formed: explicit constructor selected
};
Run Code Online (Sandbox Code Playgroud)
这个会:
struct any
{
std::atomic<int> a;
std::atomic<int> b{ 2 };
any() : a(1) {}
};
Run Code Online (Sandbox Code Playgroud)
哪种方式更好(性能)?
随着拷贝省音启用都具有相同的性能.随着拷贝省音被禁用,则在当每个实例化一个额外的复制/移动的构造函数调用拷贝初始化语法使用(即obj s = obj("value");是之一).
还有另外一种方法吗?
在大括号或相等的初始化程序语法允许一个进行直接列表初始化,以及:
class any {
public:
obj s{ "value" };
any() {}
};
Run Code Online (Sandbox Code Playgroud)
还有其他差异吗?
值得一提的其他一些差异是:
两个例子都是等价的.
虽然只有类型是可复制的或可移动的(自己检查)并且NRVO实际上已经完成(任何中途不错的编译器都会这样做).
虽然如果你有许多构造函数和构造函数链接是不合适的,第一种方法将允许你不要重复自己.
此外,您可以使用该方法定义聚合,其默认值不同于自C++ 14以来(部分)成员的聚合初始化.
他们是一样的。
就性能而言,两者都不比另一个更好,并且没有其他方法可以初始化它们。
类内初始化(示例中的第一个)的好处是初始化的顺序是隐式的。在初始化列表中,您必须明确说明顺序 - 如果顺序不正确,编译器将警告无序初始化。
从标准来看:
12.6.2.5
nonstatic data members shall be initialized in the order they were declared
in the class definition
Run Code Online (Sandbox Code Playgroud)
如果你的列表中的顺序错误,GCC 会抱怨:
main.cpp: In constructor 'C::C()':
main.cpp:51:9: warning: 'C::b' will be initialized after
main.cpp:51:6: warning: 'int C::a'
Run Code Online (Sandbox Code Playgroud)
初始化列表的好处可能是一个品味问题 - 列表是明确的,通常在源文件中。类内是隐式的(可以说),并且通常位于头文件中。
| 归档时间: |
|
| 查看次数: |
14063 次 |
| 最近记录: |