如何通过参数在构造函数中初始化数组?

时间:2017-05-24 07:09:48

标签: c++ c++11 gcc

如何通过参数在构造函数中初始化数组?我认为type (&name)[size]语法非常好,编译维护者可以轻松实现。标准中是否有一段禁止这种初始化?

代码:

struct Test
{
    char characters_[3];
    Test(char (&characters)[3]) : characters_(characters) {}
};

GCC版本:

gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609

GCC输出:

FAILED: /usr/bin/c++     -Wall -Wextra -Wconversion -pedantic -Wmissing-declarations -Wmissing-include-dirs -Wfloat-equal -std=c++11 -pg   -m32 -std=gnu++11 -MMD -MT CMakeFiles/Test.dir/test.cpp.o -MF CMakeFiles/Test.dir/test.cpp.o.d -o CMakeFiles/Test.dir/test.cpp.o -c /home/user/Desktop/programms/test/Test/test.cpp
In file included from /home/user/Desktop/programms/test/Test/test.cpp:1:0:
/home/user/Desktop/programms/test/Test/test.h: In constructor ‘Test::Test(char (&)[3])’:
/home/user/Desktop/programms/test/Test/test.h:38:54: error: array used as initializer
  Test(char (&characters)[3]) : characters_(characters) {}
                                                      ^
FAILED: /usr/bin/c++     -Wall -Wextra -Wconversion -pedantic -Wmissing-declarations -Wmissing-include-dirs -Wfloat-equal -std=c++11 -pg   -m32 -std=gnu++11 -MMD -MT CMakeFiles/Test.dir/main.cpp.o -MF CMakeFiles/Test.dir/main.cpp.o.d -o CMakeFiles/Test.dir/main.cpp.o -c /home/user/Desktop/programms/test/Test/main.cpp
In file included from /home/user/Desktop/programms/test/Test/main.cpp:4:0:
/home/user/Desktop/programms/test/Test/test.h: In constructor ‘Test::Test(char (&)[3])’:
/home/user/Desktop/programms/test/Test/test.h:38:54: error: array used as initializer
  Test(char (&characters)[3]) : characters_(characters) {}
                                                      ^

2 个答案:

答案 0 :(得分:4)

也许最简单的解决方案是使用std::array代替:

std::array<char, 3> characters;
Test(std::array<char, 3> characters) : characters(characters) {}

在C ++ 11之前,人们会将参数数组复制到构造函数体中:

Test(char (&characters)[3]) {
    std::copy(characters, characters + sizeof characters, this->characters);
}

或者会使用自定义std::array - 就像包装一样。

  

标准中是否有禁止此类初始化的段落?

肯定有(标准草案):

  

[dcl.init] / 17初始化器的语义如下。目标类型是对象或引用的类型   初始化,源类型是初始化表达式的类型。 [剪断]

     
      
  • (17.1) - 如果初始化程序是(非括号)braced-init-list或is = braced-init-list,则对象或引用是   list-initialized(8.6.4)。

  •   
  • (17.2) - 如果目的地类型是参考类型,请参阅8.6.3。

  •   
  • (17.3) - 如果目标类型是字符数组,则为char16_t数组,char32_t数组或   wchar_t数组,初始值设定项是字符串文字,见8.6.2。

  •   
  • (17.4) - 如果初始值设定项为(),则对象进行值初始化。

  •   
  • (17.5) - 否则,如果目标类型是数组,则程序格式错误。

  •   
  • [剪断]

  •   

如您所见,只有braced-init-list,字符串文字(仅限char数组)或空初始值设定项对数组有效。如果destination是数组,则不允许数组的源类型。

答案 1 :(得分:2)

在c ++ 14中,您还可以使用std::integer_sequence和专用于初始化数组的构造函数:

#include <utility>

struct Test
{
    char characters_[3];

    Test(char (&characters)[3]) : Test(characters, std::make_index_sequence<3>{}) {}


    private:
    template <std::size_t N, std::size_t... Is>
    Test(char (&characters)[N], std::index_sequence<Is...>): characters_{characters[Is]...} {}
};

int main() {
    char abc[] = {'a', 'b', 'c'};
    Test test(abc);
}

[live demo]

要在c ++ 11中应用它,您需要使用其中一个std::integer_sequence c++11 implementations