我如何使用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_cast
把initializer_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) {} };