目标:能够列出初始化对象并使默认初始化初始化所有POD为0/false
尽可能少的样板(C++ 11).
假设我有几个带有几个POD的类(想想文件格式解析).为了不应对不确定的价值观,我想默认的构造的对象是值初始化为0.例如,提供我自己的默认c'tor是memset()
小号this
工作正常,这种情况下,如没有明确地命名所有成员.
但是,这是样板.更重要的是,提供我自己的无参数默认构造函数会阻止我使用list initializer语法进行成员初始化:
class Fails1 {
public:
int a, b;
Fails1() { memset(this, 0, sizeof(*this)); }
};
Fails1 this_works;
Fails1 this_fails{ 42, 54 }; // compiler error
Run Code Online (Sandbox Code Playgroud)
我也可以添加构造函数initializer_list
,但这更是样板.我想避免所有的样板.
所以我看了编译器提供的默认构造函数,当没有用户提供的默认构造函数与各种方法相结合时如何初始化它们.这是我完全糊涂的地方:
class A {
public:
int a, b;
};
Run Code Online (Sandbox Code Playgroud)
使用这个类,我可以使用空的初始化列表和具有值的那些,而不必自己提供两个构造函数; 这是我想要的一部分.
// Example 1: default initialization
A a1;
Run Code Online (Sandbox Code Playgroud)
第一个例子使用初始化; 成员a
并且b
之后未定义(不是我想要的,我希望它们被初始化).
// Example 2: Value-initialization, so this works, I guess:
A a2 = A();
Run Code Online (Sandbox Code Playgroud)
示例2使用值初始化,之后不复制.所以这就是我想要的,但是,我也认为空的brace-init-lists会做同样的事情; 请参阅以下示例:
// Example 3: list-initialization with empty brace-init-list
A a3{};
Run Code Online (Sandbox Code Playgroud)
示例3是我认为可以解决的问题.使用空的brace-init-list进行列表初始化在8.5.4"列表初始化"中描述:特别是8.5.4.3说:"如果初始化列表没有元素,T是具有默认构造函数的类类型,则对象值初始化".但是,这会使用g ++ 4.7.2发出警告-Wextra
:
missing initializer for member ‘A::a’ [-Wmissing-field-initializers]
missing initializer for member ‘A::b’ [-Wmissing-field-initializers]
Run Code Online (Sandbox Code Playgroud)
但是,没有clang ++ 3.1的警告,所以它也可能是g ++中的一个错误.
回到我原来的问题.如何在不必提供我自己的boilerplatish默认构造函数的情况下对对象进行值初始化 - 同时保留为其成员使用列表初始化而无需提供自己的initializer_list
构造函数的能力?
像一个普通的结构
struct A { int a,b; };
Run Code Online (Sandbox Code Playgroud)
显然是一个聚合,A a {};
显然是聚合初始化并暗示值初始化(即零初始化),如您已经引用的§8.5.4/ 3所述.(特别注意以下段落中给出的示例,这与您的情况几乎完全相同.)
海湾合作委员会的警告非常误导.
在搜索现有的错误报告时,我找到了这个,你自己提交的.我认为这是正确的做法.
既然你已经制定了相关的标准部分,并且其他人在评论中做出了贡献,我将把它作为社区维基的答案.