I read this link of Stroustrup with the following code:
class X {
int a;
public:
X(int x) { if (0<x && x<=max) a=x; else throw bad_X(x); }
X() :X{42} { }
X(string s) :X{lexical_cast<int>(s)} { }
// ...
};
My question is about the line:
X() X{42}{}
Is there any differences between parentheses and curly brackets? If there is no differences can I use curly brackets in other function calls as well? Or is it just in constructor delegation?
And at last Why we should have both syntaxes? It is a little ambigous.
() uses value initialization if the parentheses are empty, or direct initialization if non-empty.
{} uses list initialization, which implies value initialization if the braces are empty, or aggregate initialization if the initialized object is an aggregate.
Since your X is a simple int, there's no difference between initializing it with () or {}.
Initialization values can be specified with parentheses or braces.
Braces initialization was introduced with C++11 and it is meant to be "uniform initialization" that can be used for all non-static variables.
Braces can be used in the place of parentheses or the equal sign and were introduced to increase uniformity and reduce confusion.
It is only a syntactical construct and does not result in performance benefits or penalties.
Related
This question already has answers here:
Different ways of initializing an object in c++
(1 answer)
What's the difference between parentheses and braces in c++ when constructing objects
(1 answer)
Closed last year.
I have a question on constructor initializer list as follows :
while specifying the initial values of members, initial values are written in ()- parenthesis according to C++ Primer book (author - Stanley Lippman). However, I have also seen {} being used to specify initial values (please refer to link - https://en.cppreference.com/w/cpp/language/constructor)
can someone explain when to use () - parenthesis and when to use {} - curly braces
thanks and regards,
-sunil puranik
According to Scott meyors Effective Modern C++, Item 7, you should basically be using {} wherever you can in the initializer list. If you are initialising a type that takes a std::initializer_list then you will need to think about it a bit more. But outside of std::vector and templates, you should basically always be using {} to construct. Why? From Scott Meyors:
Braced initialization is the most widely usable initialization syntax, it prevents
narrowing conversions, and it’s immune to C++’s most vexing parse.
Using T x{}; where T is some type, is called zero initialization.
Parenthesis () is Pre-C++11 while braces {} is from C++11 and onwards(like c++11, c++14, etc). This is just one of the many differences between the two.
For example,
Pre C++11
class MyVector
{
int x;
MyVector(): x()
{
}
};
C++11
From C++11 and onwards, you can use {} instead as shown below:
class MyVector
{
int x;
MyVector(): x{}
{
}
};
In the context of constructor initializer list(which is what your question is about) they are used to ensure proper initialization of non-static data members of a class template as explained here.
I've been going through 'A Tour of C++' and Bjarne uses the the c++11 initializer list feature in member initialization in a constructor, like so (using curly brackets):
A a;
B b;
Foo(Bar bar):
a{bar.a}, b{bar.b}
{}
This, however doesn't compile prior to c++11. What is the difference with the old member initializer list (using round brackets):
Foo(Bar bar):
a(bar.a), b(bar.b)
{}
So what is the difference and when should one be preferred over the other?
So what is the difference?
Round brackets only work for non-class types, or types with a suitable constructor for the number of arguments in the brackets.
Squiggly braces work for these, and also for aggregates - simple struct or array types with no constructor. So the following will work:
struct {
int a,b;
} aggregate;
int array[2];
Foo() : aggregate{1,2}, array{3,4} {}
Finally, braces will match a constructor taking a suitably-typed initializer_list, rather than a constructor with parameter(s) to match the arguments. For example:
std::vector<int> v1;
std::vector<int> v2;
Foo() :
v1(10,2), // 10 elements with value 2
v2{10,2} // 2 elements with value 10,2
{}
when should one be preferred over the other?
Prefer round brackets if you want to make it clearer that the initialisation is using a constructor rather than aggregate or initializer_list; or to force use of a specific constructor.
Prefer braces when you need a form of initialisation not otherwise supported; or when you just want the initialisation to "do the right thing".
In the cases where both do the same thing, the choice is largely aesthetic.
There can be a difference in a few really annoying edge cases:
std::vector<int> v{3, 2}; // constructs a vector containing [3, 2]
std::vector<int> u(3, 2); // constructs a vector containing [2, 2, 2]
That is true regardless of whether v and u are just variables in a function or are members of a class initialized in an initialization list.
But outside the cases where a std::initializer_list<T> constructor overlaps with a normal constructor taking the same number of arguments, there is no difference.
The short description is: the notation in the member initializer list matches that of variables initialized elsewhere. Sadly, the description of what it does is not as easy at all because there are two somewhat conflicting changes relating to the use of curly braces for constructor calls:
The unified initialization syntax was intended to make to make have all constructions use curly braces and it would just call the corresponding constructor, even if it is the default argument or the type doesn't have a constructor at all and direct initialization is used.
To support variable number of arguments, curly braces can be used to provide an std::initializer_list<T> without an extra pair of parenthesis/curly braces. If there is a constructor taking an std::initializer_list<T> (for a suitable type T) this constructor is used when using curly braces.
Put differently, if there is no std::initializer_list<T> constructor but some other user defined constructor the use of parenthesis and curly braces is equivalent. Otherwise it calls the std::initializer_list<T> constructor. ... and I guess, I'm missing a few details as the entire initialization is actually quite complicated.
I was watching MVA's(Microsoft Visual Academy's) tutorials and I came across these two operators i.e. {} and = to pass in the value to variables. I have done C programming so I am pretty much aware of the assignment operator =. But {} is not in any language I did so far.
Kate is teaching the C++ course so she told that {} is used for copying.
But I was using the operator {} in the class below and it shows some error when I try to do this:
this->_width{new_width};
whereas below one works:
this->_width = new_width;
Why so? I am also using {} to pass values in constructor but then they work perfectly. Only Problem is with member fucntions.
class Rectangle
{
public:
void resize(int new_height, int new_width) { this->_width{new_width ; this->_height{new_height}; //member function
Rectangle(): _width{} , height{} {} //constructor
private:
int _width;
int _height;
};
{} can be used to initialise variables in C++11 in the same way that they are used to initialise arrays and structures in C.
This has been introduced primarily to provide consistency in language syntax (initialising with {} will work in all contexts, whereas initialising using the assignment operator or () will work in specific contexts.
There is a further advantage to list initialisation in that it prevents narrowing - i.e. it prevents you from providing an integer when a double is required, or a short when an integer is required. In this way it can help to reduce bugs.
Note that {} cannot be used to pass values to a function - only to construct new objects.
This page is also worth reading
Using {} is called uniform initialization in this context. It was introduced mainly for two reasons.
First, as the name indicates, initialization is uniform, that is it looks and works the same for single objects, arrays, containers that accept initializer lists, etc.
Second, and equally important, it is impossible to get a most vexing parse using curly braces, which is quite possible unintentionally otherwise:
A a(); // What does this do? What was probably intended?
B b{}; // And what does this do?
Also, as a bonus (kudos to #Richard Hodges), you avoid narrowing conversions using uniform initialization.
To literally answer the question "which one should I use?", you should preferrably use {} as it has only advantages, and no disadvantages (plus, Bjarne Stroustrup recommends using it).
Non-static data members may be initialized in one of two ways:
1) In the member initializer list of the constructor.
struct S {
int n;
std::string s;
S() : n(7) // direct-initializes n, default-initializes s
{ }
};
2) Through a brace-or-equal initializer, which is simply an initializer included in the member declaration, which is used if the member is omitted in the member initializer list
struct S {
int n = 7;
std::string s{'a', 'b', 'c'};
S() // copy-initializes n, list-initializes s
{ }
};
You may use brace initializers in the member declaration.
Also, from the standard, N4296, § 9.2, paragraph 4:
A brace-or-equal-initializer shall appear only in the declaration of
a data member.
I saw a code where a programmer used curly braces to initialize a variable
int var{ 5 };
instead of using the assignment operator
int var = 5;
I know assigning a value to lhs variable using curly braces is a C++11 syntax. Is there any difference between using the two?
Thank you for replies.
They are different kinds of initialization:
T a{b}; // list initialization
T a = b; // copy initialization
T a(b); // direct initialization
There is no difference for ints but there can definitely be differences for other types. For instance, copy initialization might fail if your constructor is explicit, whereas the other two would succeed. List initialization disallows narrowing conversions, but for the other two those are fine.
As far as I know, there is no difference in the two for integers. The {} syntax was made to(however, not limited to, because it is also used for initializer_list) prevent programmers from triggering http://en.wikipedia.org/wiki/Most_vexing_parse, and so instead of std::vector<int> v() to initialize v you write std::vector<int> v{};.
The {} has different behaviours depending on the usage, it can be a call to constructor, a initializer list and even a list of values to initialize members of user-defined class in order of definition.
Example of the last:
class Q{
public:
int a;
int b;
float f;
};
int main()
{
Q q{2, 5, 3.25f};
}
I've been going through 'A Tour of C++' and Bjarne uses the the c++11 initializer list feature in member initialization in a constructor, like so (using curly brackets):
A a;
B b;
Foo(Bar bar):
a{bar.a}, b{bar.b}
{}
This, however doesn't compile prior to c++11. What is the difference with the old member initializer list (using round brackets):
Foo(Bar bar):
a(bar.a), b(bar.b)
{}
So what is the difference and when should one be preferred over the other?
So what is the difference?
Round brackets only work for non-class types, or types with a suitable constructor for the number of arguments in the brackets.
Squiggly braces work for these, and also for aggregates - simple struct or array types with no constructor. So the following will work:
struct {
int a,b;
} aggregate;
int array[2];
Foo() : aggregate{1,2}, array{3,4} {}
Finally, braces will match a constructor taking a suitably-typed initializer_list, rather than a constructor with parameter(s) to match the arguments. For example:
std::vector<int> v1;
std::vector<int> v2;
Foo() :
v1(10,2), // 10 elements with value 2
v2{10,2} // 2 elements with value 10,2
{}
when should one be preferred over the other?
Prefer round brackets if you want to make it clearer that the initialisation is using a constructor rather than aggregate or initializer_list; or to force use of a specific constructor.
Prefer braces when you need a form of initialisation not otherwise supported; or when you just want the initialisation to "do the right thing".
In the cases where both do the same thing, the choice is largely aesthetic.
There can be a difference in a few really annoying edge cases:
std::vector<int> v{3, 2}; // constructs a vector containing [3, 2]
std::vector<int> u(3, 2); // constructs a vector containing [2, 2, 2]
That is true regardless of whether v and u are just variables in a function or are members of a class initialized in an initialization list.
But outside the cases where a std::initializer_list<T> constructor overlaps with a normal constructor taking the same number of arguments, there is no difference.
The short description is: the notation in the member initializer list matches that of variables initialized elsewhere. Sadly, the description of what it does is not as easy at all because there are two somewhat conflicting changes relating to the use of curly braces for constructor calls:
The unified initialization syntax was intended to make to make have all constructions use curly braces and it would just call the corresponding constructor, even if it is the default argument or the type doesn't have a constructor at all and direct initialization is used.
To support variable number of arguments, curly braces can be used to provide an std::initializer_list<T> without an extra pair of parenthesis/curly braces. If there is a constructor taking an std::initializer_list<T> (for a suitable type T) this constructor is used when using curly braces.
Put differently, if there is no std::initializer_list<T> constructor but some other user defined constructor the use of parenthesis and curly braces is equivalent. Otherwise it calls the std::initializer_list<T> constructor. ... and I guess, I'm missing a few details as the entire initialization is actually quite complicated.