我如何使用initializer_list初始化成员数组?

我正在加快C ++ 0x的速度,并用g ++ 4.6进行testing

我只是尝试下面的代码,认为它会工作,但它不会编译。 我得到的错误:

incompatible types in assignment of 'std::initializer_list<const int>' to 'const int [2]'

 struct Foo { int const data[2]; Foo(std::initializer_list<int const>& ini) : data(ini) {} }; Foo f = {1,3}; 

您可以使用可变参数模板构造函数来代替初始化程序列表构造函数:

 struct foo { int x[2]; template <typename... T> foo(T... ts) : x{ts...} { // note the use of brace-init-list } }; int main() { foo f1(1,2); // OK foo f2{1,2}; // Also OK foo f3(42); // OK; x[1] zero-initialized foo f4(1,2,3); // Error: too many initializers foo f5(3.14); // Error: narrowing conversion not allowed foo f6("foo"); // Error: no conversion from const char* to int } 

编辑: 如果你可以没有常量的生活,另一种方法是跳过初始化并填充函数体中的数组:

 struct foo { int x[2]; // or std::array<int, 2> x; foo(std::initializer_list<int> il) { std::copy(il.begin(), il.end(), x); // or std::copy(il.begin(), il.end(), x.begin()); // or x.fill(il.begin()); } } 

但是,这样,您就失去了前一种解决scheme所提供的编译时间界限。

据我所知,使用构造函数的参数(8.5.4 / 1)的列表初始化应该是合法的,并且解决了上述的许多问题。 但是,ideone.com上的GCC 4.5.1无法匹配构造函数并拒绝它。

 #include <array> struct Foo { std::array< int, 2 > const data; Foo(std::array<int, 2> const& ini) // parameter type specifies size = 2 : data( ini ) {} }; Foo f( {1,3} ); // list-initialize function argument per 8.5.4/1 

如果你真的坚持initializer_list ,你可以使用reinterpret_castinitializer_list的底层数组变成一个C风格的数组。

 Foo(std::initializer_list<int> ini) // pass without reference- or cv-qualification : data( reinterpret_cast< std::array< int, 2 > const & >( * ini.begin() ) 

根据这里的讨论:

Potatoswatter的第二个解决scheme的正确语法是:

 Foo f( {{1,3}} ); //two braces 

有点难看,不符合常用用法

只是一个很大的JohannesD答案的一小部分。

如果没有parameter passing给foo构造函数,数组将被默认初始化。 但有时候你想保持底层数组未被初始化(也许出于性能的原因)。 您不能添加默认构造函数与可变模板的默认构造函数。 解决方法是variadic-templated构造函数的附加参数,以区别于零参数构造函数:

 template<class T, size_t rows, size_t cols> class array2d { std::array<T, rows * cols> m_Data; public: array2d() {} template <typename T, typename... Types> array2d(T t, Types... ts) : m_Data{ { t, ts... } } {} }; 

所以,现在你可以支持initilize对象,或者让它不被初始化:

 array2d<int, 6, 8> arr = { 0, 1, 2, 3 }; // contains 0, 1, 2, 3, 0, 0, 0, ... array2d<int, 6, 8> arr2; // contains garbage 

更新31/07/2016

三年过去了,编译器实现者改进了产品的标准符合性,直到默认的构造函数在可变参数构造函数中不被认为是模糊的。 所以,在实践中,我们不需要额外的variables构造函数来消除构造函数的歧义。

 array2d() {} 

 array2d() = default; 

如果对象被构造成没有参数的话,将会使数组未被初始化。 这一行为在所有主要的编译器上都是一致的。 完整示例( rextester ):

 #include <array> #include <iostream> template<class T, size_t rows, size_t cols> class array2d { public: std::array<T, rows * cols> m_Data; array2d() = default; template <typename... Types> array2d(Types... ts) : m_Data{ { ts... } } {} }; int main() { array2d<int, 6, 8> arr_init = { 0, 1, 2, 3 }; array2d<int, 6, 8> arr_default; std::cout << "Initialized: \n"; for(const auto& a : arr_init.m_Data) std::cout << a << " "; std::cout << "\n"; std::cout << "Default: \n"; for(const auto& a : arr_default.m_Data) std::cout << a << " "; std::cout << "\n"; } 

输出:

 Initialized: 0 1 2 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Default: 2 0 -519559849 32558 1 32558 0 0 -519634912 32558 -526739248 32558 1 0 2 0 6295032 0 -519531243 32558 0 0 -1716075168 32765 6295648 0 4196192 0 6295648 0 -526527271 32558 1 0 2 0 6295032 0 4196845 0 124 0 0 0 4196768 0 4196518 0 

删除默认的构造函数仍然导致可调参数被调用,数组被默认初始化(在我们的例子中是全零)。

感谢@Alek,因为这个话题引起了人们的注意,也感谢所有在编译器开发方面努力的人。

你不能,数组不是像其他types(并没有构造函数采取std :: initializer_list)。

试试这个:

 struct Foo { const std::vector<int> data; Foo(std::initializer_list<int> ini) : data(ini) {} };