为了帮助您明白这一点,我提供了我的代码:(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
。但是,当我使用mac
在g++ -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
个对象分别使用10
和20
初始化。但是我后来尝试过的语法vector<test> array[2] {10,20}
又错了。
我不知道这里发生了什么,完全迷失了。是不是{10,20}
初始化列表类型?
如果您能解释这里发生了什么,以及如何初始化不同大小的矢量数组(请不要使用规避方法),我真的很感激。我想知道语法的确切含义。
答案 0 :(得分:4)
首先,explicit
构造函数允许直接初始化,但不允许复制初始化。
(强调我的)
每个
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
提供带有一个参数的构造函数(只是取消注释我的代码中的行),编译器就不会抱怨了。
如果您提供的构造函数可用于隐式转换int
到test
,那么{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}}也将是未初始化的。