C ++:初始化(新)不同初始大小

时间:2018-04-30 12:36:33

标签: c++ arrays vector initialization initializer-list

为了帮助您明白这一点,我提供了我的代码:(main.cpp),只涉及一个文件。

#include <iostream>
#include <vector>
using namespace std;
class test{
public : 
    int member {0};
    void fun(){cout << "member is " << member << endl;}
    test(){}
    //test(int param) : member(param){} //this line is commented.
};

int main()
{
    vector<test> *vp = new vector<test>[2] {{10},{20}};
    //vector<test> array[2] {{10},{20}};//this won't work either.
    cout << "size of vp[0] is " << vp[0].size() << endl;
    cout << "size of vp[1] is " << vp[1].size() << endl;
    return 0;
}

我打算将vp[0]初始化为10,将vp[1]初始化为20。但是,当我使用macg++ -std=c++11 main.cpp -o main上编译时,它抱怨:

main.cpp:14:45: error: chosen constructor is explicit in copy-initialization
    vector<test> *vp = new vector<test>[2] {{10},{20}};
                                            ^~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:517:14: note: 
      constructor declared here
    explicit vector(size_type __n);
             ^
main.cpp:14:50: error: chosen constructor is explicit in copy-initialization
    vector<test> *vp = new vector<test>[2] {{10},{20}};
                                                 ^~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:517:14: note: 
      constructor declared here
    explicit vector(size_type __n);
         ^

在CentOS Linux中使用相同的命令我得到了

main.cpp: In function ‘int main()’:
main.cpp:14:54: error: converting to ‘std::vector<test>’ from initializer list would use explicit constructor ‘std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>::size_type, const allocator_type&) [with _Tp = test; _Alloc = std::allocator<test>; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<test>]’
     vector<test> *vp = new vector<test>[2] {{10},{20}};
                                                      ^
main.cpp:14:54: error: converting to ‘std::vector<test>’ from initializer list would use explicit constructor ‘std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>::size_type, const allocator_type&) [with _Tp = test; _Alloc = std::allocator<test>; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<test>]’

这里发生了什么?为什么它与关键字explicit有关? 我知道vector有几个构造函数(比如带有initializer-list类型参数的构造函数)。如果我初始化像vector<test> temp {10}这样的向量,则会将向量初始化为大小为10而没有任何explicit问题。我不知道vector<test> array[2] {{10},{20}}导致我犯错误的内部隐藏的内容。

有趣的是,如果我为类test提供带有一个参数的构造函数(只是取消注释我的代码中的行),编译器就不会抱怨了。但vector<test> array[2] {{10},{20}}的含义已更改为初始化向量array[0],其中2 test个对象分别使用1020初始化。但是我后来尝试过的语法vector<test> array[2] {10,20}又错了。

我不知道这里发生了什么,完全迷失了。是不是{10,20}初始化列表类型?

如果您能解释这里发生了什么,以及如何初始化不同大小的矢量数组(请不要使用规避方法),我真的很感激。我想知道语法的确切含义。

2 个答案:

答案 0 :(得分:4)

首先,explicit构造函数允许直接初始化,但不允许复制初始化。

然后,在aggregate initialization

(强调我的)

  

每个direct public base, (since C++17)数组元素或非静态类成员,按照类定义中数组下标/外观的顺序,从初始化列表的相应子句中复制初始化

这意味着new vector<test>[2] {{10},{20}};{10}{20}用于复制初始化 vector<test>元素;然后不考虑explicit构造函数。

  

如果我初始化像vector<test> temp {10}这样的向量,则会将向量初始化为大小为10而没有任何explicit问题。

因为direct initialization中允许使用explicit构造函数,

  

直接初始化比复制初始化更宽松:复制初始化仅考虑非显式构造函数和非显式用户定义转换函数,而直接初始化考虑所有构造函数和所有用户定义的转换函数。

出于同样的原因new vector<test>[2] {std::vector<test>{10},std::vector<test>{20}};也有效。

顺便说一句:

  

如果我为类test提供带有一个参数的构造函数(只是取消注释我的代码中的行),编译器就不会抱怨了。

如果您提供的构造函数可用于隐式转换inttest,那么{10}可用于构造std::initializer_list<test>,然后构造函数{ {1}}调用std::vector<test>,因为它总是首选。顺便说一下如果你创建std::initializer_list<test> test的构造函数,代码也会失败。

答案 1 :(得分:2)

您正在使用代码vector<test>初始化vector<test> array[2] {{10},{20}}个对象。您收到的错误来自使用explicit vector。此count构造函数将构造test默认构造的explicit个对象 因此,例如,如果未将其定义为array[0],您最终会得到包含10个默认构造的test对象的array[1],而test包含20个默认构造的vector vector<test> foo[] = { vector<test>{ 10 }, vector<test>{ 20 } } 1}}对象。如果您打算这样做,则必须明确构造vector个对象:

eplicit

你真的想在vector中构建测试对象,所以这个test:test(int param)实际上是在保护你免于意外地结束分配非预期的{{10},{20}}

当您添加explicit构造函数vector时,仍然无法使用vector[0] int array[2] = {42}构造函数。但现在可以将其视为vector的{​​{3}}。但是,如果你完成了:lea string, %eax add $8, %eax movzbl (%eax), %eax 和2 nd 元素将被零初始化;在这种情况下,你的2 nd {{1}}也将是未初始化的。