There is a pitfall - you can't just blindly use braces everywhere. The problem is that vector v below only has one element with the value 2: std::vector<int> v{2}
While vector u has 2 elements with value 0: std::vector<int> u(2)
(The pitfall doesn't apply to your case.)
If you need to use the parentheses but aren't allowed, you can say class a { std::vector<int> v = std::vector<int>(2); };
Or do the initialization in a member initializer list:
Yeah - I haven't yet recovered from a couple of nights ago (never again during the week... - I currently make a good impression of 'Night Of The Living Dead'). I saw mbozzi's post and interpreted it wrongly (as a language version issue) rather than a syntax issue. I've altered my previous posts with a strike-through!
The problem is that a class member variable direct initialization with params won’t work. It is tried to be treated as a function declaration (the most vexing parse issue) - hence the error.
In a class either use {} syntax (as repeatedly correctly stated by Borges) or as mbozzi's post adjusted for a 2d-vector (using equals initializer - again as correctly stated by Borges above):
You do know that C++11 did add brace initialization (to skim around the most vexing parse) and the default member initialization.
Hence, before C++11 there was no default member initialization at all and adding anything that could fall to most vexing parse definitely was not the objective of C++11, I reckon.
You mean why not allow parentheses to specify default member initializers?
I think the answer has already been given by keskiverto. They wanted to avoid the "most vexing parse" problem. That's the reason I have also heard.
I think there might also been an overexcitement about the new "uniform initialization" at the time, and a lack of understanding that we still need/want to use these other initialization syntaxes as often as we still do.
I looked at some old papers and it seems like the original proposal was to allow all kinds of initialization syntaxes.
N1959 wrote:
The basic idea is to allow non-static attributes of class and struct types to be initialized where declared. All of the same initialization syntaxes may be used as for initialization of local variables.
In a later version of the proposal the wording had changed:
N2628 wrote:
The basic idea is to allow non-static data members of class types to be initialized where declared. The goal is that all of the same initialization syntaxes may be used as for initialization of local variables; [...] This goal will not be reached completely, however, because to avoid parsing problems, we no longer propose to allow initializers of the “( expression-list )” form as explained below. On the other hand, there now seems to be a consensus on the use of {} for initializers (N2575), so we use that form for some examples that used parentheses in earlier versions of this paper.
#include <vector>
#include <iostream>
using Matrix = std::vector < std::vector <double> >;
void display(const Matrix& m) {
std::cout << m.size() << '\n';
for (size_t c {}; constauto & y : m)
std::cout << c++ << " has " << y.size() << " elements\n";
std::cout << '\n';
}
int main() {
Matrix vv1 { 2 };
Matrix vv2(2);
std::cout << "size of vv1: ";
display(vv1);
std::cout << "size of vv2: ";
display(vv2);
vv1[0].push_back(2);
vv2[1].push_back(3);
vv2[1].push_back(4);
std::cout << "After adding elements\nsize of vv1: ";
display(vv1);
std::cout << "size of vv2: ";
display(vv2);
std::cout << vv1[0][0] << '\n';
std::cout << vv2[1][1] << '\n';
}
then it displays as expected:
size of vv1: 2
0 has 0 elements
1 has 0 elements
size of vv2: 2
0 has 0 elements
1 has 0 elements
After adding elements
size of vv1: 2
0 has 1 elements
1 has 0 elements
size of vv2: 2
0 has 0 elements
1 has 2 elements
2
4