如何使用成员初始化列表来初始化一个数组?

8
class A {
public:
   A();

private:
   char a[5];
   int* ptr;
};

A::A() : a(0), ptr(0) { }

这个对吗?

2个回答

18
在C++03中,对于C数组唯一明智的做法是进行值初始化(在C++11及以上版本中可以进行列表初始化)。
根据C++03标准 §8.5/7:
一个初始化器为一组空括号即()的对象将被进行值初始化。
并且根据§8.5/5:
对于类型为T的对象进行值初始化意味着:
- 如果T是一个带有用户声明构造函数的类类型,则调用T的默认构造函数(如果T没有可访问的默认构造函数,则该初始化是不合法的); - 如果T是一个非联合类类型而没有用户声明的构造函数,则对T的每个非静态数据成员和基类组件进行值初始化; - 如果T是一个数组类型,则对每个元素进行值初始化; - 否则,对象将被零初始化。
对于类型为T的对象进行零初始化意味着:
- 如果T是一个标量类型,则该对象被设置为转换为T后的值0(零); - 如果T是一个非联合类类型,则每个非静态数据成员和每个基类子对象都被零初始化; - 如果T是一个联合类型,则该对象的第一个命名数据成员被零初始化; - 如果T是一个数组类型,则对每个元素进行零初始化; - 如果T是一个引用类型,则不进行初始化。
因此,如果您的构造函数定义更改为:
A::A() : a(), ptr() { }

如果你这样做,就能确保在构造完成后,A::a 的所有 5 个元素都将具有值 '\0',而 A::ptr 将为 null。


3

抱歉,C++不支持像这样初始化数组。

你只能在 A 的构造函数中为其成员赋值,或者如果你不关心值是什么的话,可以使用值初始化:

struct A {
   int x[5];
   A() : x();
};

C++0x确实允许您提供所有值:

struct A {
   int x[5];
   A() : x{1,2,3,4,5} {}
};

请注意,由于数组不是类对象,因此您将无法执行以下操作:
struct A {
   int x[5];
   A(std::initializer_list<int[5]>& i) // or whatever the T should be
      : x{i} // or x(i)
        {}
}
A a({1,2,3,4,5)};

在 C++0x 中,人们普遍认为(我希望如此!)应该始终使用 std::array<> 而不是 C 数组,在构造函数初始化列表中可以方便地初始化并从静态成员函数返回。 - ildjarn
@GMan:确实如此。您无法使用std :: initializer_list <>初始化数组,因为数组没有构造函数。但您仍然需要在封闭类型的构造函数中迭代某些内容。而这并不是真正的问题的原因就是ildjarn所说的那样。 - Lightness Races in Orbit
g++ 4.5.2对于A() : a{1, 2, 3, 4, 5} { }没有问题(当然,并不意味着它在C++0x中是允许的)。 - James McNellis
@JamesMcNellis:既然你提到了,可能我一开始是无意中想到了std::initializer_list<>的情况;基本的逐元素初始化确实是有效的,不是吗? - Lightness Races in Orbit
std::array<>是一个聚合体。它没有除默认/复制和(可能)移动之外的构造函数(因此也没有初始化列表构造函数)。请注意,您可以编写像template<typename ...T> A(T... t):x{t...} { }这样的构造函数,然后编写A a{1, 2, 3},但这看起来会创建许多小的模板实例化。不确定它会导致多少代码膨胀。请参见https://dev59.com/QW855IYBdhLWcg3w1oE8#4118050。 - Johannes Schaub - litb
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接