【发布时间】:2012-12-25 12:00:40
【问题描述】:
目标:能够列表初始化对象并拥有默认值
初始化将所有 POD 初始化为 0/false,使用尽可能少的样板
尽可能 (C++11)。
假设我有几个类和几个 POD(想想文件格式
解析)。为了不处理未定义的值,我想要
默认构造对象的值初始化为 0。例如,
提供我自己的默认 c'tor memset()s this 适用于
在这种情况下,明确命名所有成员也是如此。
但是,这是样板文件。更重要的是提供我自己的 无参数默认构造函数阻止我使用列表 成员初始化的初始化语法:
class Fails1 {
public:
int a, b;
Fails1() { memset(this, 0, sizeof(*this)); }
};
Fails1 this_works;
Fails1 this_fails{ 42, 54 }; // compiler error
我也可以为initializer_list 添加构造函数,但是
那更是样板。我想避免所有这些样板文件。
所以我查看了编译器提供的默认构造函数 没有用户提供的默认构造函数与 如何初始化它们的各种方法。这是我得到的地方 完全糊涂了:
class A {
public:
int a, b;
};
有了这个类,我可以使用空的初始化列表和那些 具有值而不必自己提供两个构造函数;那 是我想要的一部分。
// Example 1: default initialization
A a1;
第一个例子使用初始化;成员 a 和 b 是
之后未定义(不是我想要的,我希望它们成为
值初始化)。
// Example 2: Value-initialization, so this works, I guess:
A a2 = A();
示例 2 使用值初始化,之后不复制。这就是我想要的,但是,我也认为空的大括号初始化列表会做同样的事情;看下面的例子:
// Example 3: list-initialization with empty brace-init-list
A a3{};
示例 3 是我认为可以解决问题的方法。列表初始化
8.5.4 中描述了一个空的大括号初始化列表
“列表初始化”:;特别是 8.5.4.3 说:“如果初始化
list 没有元素并且 T 是具有默认构造函数的类类型,
对象值初始化”。但是,这会在 g++ 4.7.2 中发出警告
-Wextra:
missing initializer for member ‘A::a’ [-Wmissing-field-initializers]
missing initializer for member ‘A::b’ [-Wmissing-field-initializers]
不过,clang++ 3.1 没有警告,所以它也可能是 g++ 中的一个错误。
回到我原来的问题。如何对对象进行值初始化
无需提供我自己的样板默认构造函数——
同时保留对其成员使用列表初始化的能力
无需提供我自己的initializer_list 构造函数?
【问题讨论】:
-
我不觉得
A() : a{}, b{} {}太样板了,但如果这些警告不存在并且A a{}编译时没有警告会更好。 -
提供默认ctor还需要我提供
initializer_list默认ctor。现在将其乘以每个班级 > 20 个标题字段乘以 > 10 个班级,我肯定会称其为样板。当然这是旁观者的看法,所以我的样板文件很可能是您的正常编码风格,这完全可以:) -
在 C++03 中根本不允许在构造函数中使用
memset,因为用户定义的构造函数的存在使类成为非 POD。在 C++11 中,这是有点放松的,因此在某些情况下是允许的。但是,我看到一把大枪正对准你的脚。 -
@MoritzBunkus,说实话,到那时,我可能会禁用警告。这与你在做什么无关。
-
@BoPersson:好的,不知道这一点,但这让我的问题对我来说更加重要,以免产生太多样板。