问题
To help you get the point, I give my codes:(main.cpp),only one file involved.
#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;
}
I intend to initialize vp[0]
to size 10 and vp[1]
to size 20
. However when I compiled it on mac
using g++ -std=c++11 main.cpp -o main
it complained:
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);
^
In CentOS Linux using the same command and I got
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>]’
What is going on here? Why does it have anything to do with keyword explicit
?
I know vector have several constructors(such as the one with initializer-list type argument). If I initialize the vector like vector<test> temp {10}
, this would initialize vector to be of size 10 without any explicit
concerns. I don't know what is hidden inside when it comes to vector<test> array[2] {{10},{20}}
that cause me the bug.
Interestingly, if I provide class test
with a constructor with one argument(just uncomment the line in my code), the compiler does not complain at all. But the meaning of vector<test> array[2] {{10},{20}}
changed to initialize the vector array[0]
with 2 test
type objects initialized with 10
and 20
respectively. But the syntax vector<test> array[2] {10,20}
,which i tried later, is wrong again.
I don't know what is going on here and am totally lost. Isn't {10,20}
of initializer-list type too?
I really appreciate it if you can explain what's going on here, and how to initialize an array of vector of different size(please do not use circumventing ways). I want to know what does the syntax means exactly.
回答1:
Firstly, explicit
constructor is allowed in direct-initialization, but not copy-initialization.
Then, in aggregate initialization,
(emphasis mine)
Each
direct public base, (since C++17)
array element, or non-static class member, in order of array subscript/appearance in the class definition, is copy-initialized from the corresponding clause of the initializer list.
That means for new vector<test>[2] {{10},{20}};
, {10}
and {20}
are used to copy-initialize the vector<test>
elements; then the explicit
constructors are not considered.
And
If I initialize the vector like
vector<test> temp {10}
, this would initialize vector to be of size 10 without anyexplicit
concerns.
Because explicit
constructor is allowed in direct initialization,
Direct-initialization is more permissive than copy-initialization: copy-initialization only considers non-explicit constructors and non-explicit user-defined conversion functions, while direct-initialization considers all constructors and all user-defined conversion functions.
For the same reason new vector<test>[2] {std::vector<test>{10},std::vector<test>{20}};
works too.
BTW:
if I provide class
test
with a constructor with one argument(just uncomment the line in my code), the compiler does not complain at all.
If you provide a constructor which could be used to convert int
to test
implicitly, then {10}
could be used to construct an std::initializer_list<test>
, then the constructor of std::vector<test>
which taking std::initializer_list<test>
is invoked because it's always preferred. BTW If you make the constructor of test
explicit
the code would fail too.
回答2:
You are initializing vector<test>
objects with the code: vector<test> array[2] {{10},{20}}
. The error you're getting is from using the vector::vector(size_t count) constructor which is explicit
. This vector
constructor would construct count
default constructed test
objects.
So for example if this hadn't been defined as explicit
you would have ended up with array[0]
containing 10 default constructed test
objects, and array[1]
containing 20 default constructed test
object. If you had intended to do this you would have to have constructed the vector
objects explicitly:
vector<test> foo[] = { vector<test>{ 10 }, vector<test>{ 20 } }
You really wanted to construct test objects into the vector
s so this eplicit
is in fact protecting you from accidentally ending up allocating unintended vector
s.
When you add in the test:test(int param)
constructor {{10},{20}}
still fails to use the explicit
vector
constructor. But this can now be treated as list initialization of vector[0]
. But similarly to if you'd done: int array[2] = {42}
and the 2nd element would be zero-initialized; so too your 2ndvector
will be uninitialized in this case.
来源:https://stackoverflow.com/questions/50100705/c-initializenew-an-array-of-vector-of-different-initial-size