This question already has answers here:
What are the advantages of list initialization (using curly braces)?
(5 answers)
Closed 9 years ago.
I saw a initialization syntax which is new for me. I searched on google and here but I couldn't find something useful.
int a = 0;
int a = {0};
int a{0}; // <- this is new for me
Why do I need third style while others exist? What is the difference between each exactly?
Thanks.
You may be interested by C++11 initializer lists. They might not explain the third example, but they are useful, especially for real class objects.
Your code int a{0}; is called uniform initialization in C++11. See also most vexing parse wikipage (as commented by Joe Z).
Take time to at least read the C++11 wikipage. The new features of C++11 makes it almost a different language than C++03.
This form of initialization is referred to as list initialization in C++11.
When used with variables of built-in type, list initialization is different in one way: you can't list initialize variables of built-in type if the initializer might lead to the loss of information.
double pi = 3.1415926;
int a(pi); //fine
int a{pi}; //compile error
Related
This question already has answers here:
using std::initializer_list as a member variable [duplicate]
(1 answer)
Can it be safe to keep a copy of an std::initializer_list? What is the rationale?
(1 answer)
Closed 3 years ago.
Recently I have debugged strange issue appeared as result of allocation objects of some complex structs (constructor is not defined). As result I detected that if I have, for example:
struct A {
int b;
std::initializer_list<Type*> c;
};
then objects a of this struct A allocated using new and statically are different:
A a {1, {new Type(), new Type()}};
does what I wanted, but
A* a = new A {1, {new Type(), new Type()}};
performs some buggy initialization of c member.
Are these cases different by C++ standard, compiler's bad behavior or my mistake? Tested on VS2017.
If you would read the documentation, you could avoid such problems: https://en.cppreference.com/w/cpp/utility/initializer_list.
The underlying array is not guaranteed to exist after the lifetime of the original initializer list object has ended. The storage for std::initializer_list is unspecified (i.e. it could be automatic, temporary, or static read-only memory, depending on the situation).
So as suggested in the link in comments, you should store data in a permanent container (here an std::vector would probably be the proper choice).
This question already has answers here:
Direct Initialization vs Copy Initialization for Primitives
(4 answers)
Closed 5 years ago.
Recently I saw a quite old code in C++, where int var(12) was used instead of int var=12. Why does it work? And should I avoid writing this style of declaration?
There are three ways of initializing variables are valid in C++.
type identifier = initial_value;
For example, to declare a variable of type int called x and initialize it to a value of zero from the same moment it is declared, we can write:
int a=5; // initial value: 5
type identifier (initial_value);
A second method, known as constructor initialization (introduced by the C++ language), encloses the initial value between parentheses (()):
int b(3); // initial value: 3
type identifier {initial_value};
Finally, a third method, known as uniform initialization, similar to the above, but using curly braces ({}) instead of parentheses (this was introduced by the revision of the C++ standard, in 2011):
int c{2}; // initial value: 2
You should check Documentation section Initialization of variables
This question already has answers here:
What do the following phrases mean in C++: zero-, default- and value-initialization?
(2 answers)
Closed 6 years ago.
Question1:
struct S
{
size_t size;
int j;
int k;
int l;
};
S s={sizeof(S)};
Doest C++ standard say,the above {} will initialize "j,k,l" to 0?
Seems it will do, is it part of cpp standard?
Question2:
int main()
{
int* pi=new int[5];
for(int i=0;i<5;++i)
cout<<pi[i]<<',';
return 0;
}
Here the elements in pointer to array(pi) are not initialized, my running result may look like
6785200,6782912,0,0,0,
But if I change it to
int main()
{
int* pi=new int[5]();//use ()
for(int i=0;i<5;++i)
cout<<pi[i]<<',';
return 0;
}
Then, all pi elements are "0". Seems "()" will give elements a "0" value. Is this part of cpp standard?
I also tried to give another value using "()" like this:
int* pi=new int[5](7);
But it fails compilation. How could I give initialization values to an pointer to array with all elements having same value?
Question 1
Yes, it is guarantied by aggregate initialization
in particular:
If the number of initializer clauses is less than the number of members [and bases (since C++17)] or initializer list is completely empty, the remaining members [and bases (since C++17)] are initialized [by their default initializers, if provided in the class definition, and otherwise (since C++14)] by empty lists, which performs value-initialization. If a member of a reference type is one of these remaining members, the program is ill-formed (references cannot be value-initialized).
.
Question 2
Use std::vector:
std::vector<int> pi(5, 7);
There is a perfect answer to question 1 already, I will answer question 2.
Yes, your observation is correct. Adding () after the new turns default initialization of the elements into value initialization. The first form does nothing with created objects (so you observe random numbers), but the value initialization will initialize members - and in this case, will set elements to 0. Unfortunately, there is no way to perform a specific initialization for dynamic int arrays - you can either leave them uninititalized or value-initialize them (to 0).
Using std::vector solves this problem.
This question already has answers here:
Is there a difference between copy initialization and direct initialization?
(9 answers)
Closed 7 years ago.
Why C++ gives two ways to initialize variable?
First way is C-type initialization where we assign value to the variable at the place where we define it.
int a = 0;
Another way, constructor initialization which is done by enclosing the initial value between parentheses ().
int a(0);
My question is what was reason that the creators of C++ were forced to introduce new way to initialize variable. Although C-style initialization was doing the job.
int a = 0; exists for legacy (and because it feels natural, especially for built-in types), and int a(0) exists for explicitness and consistency - there are situations where you may want a more complicated copy constructor which takes multiple arguments or arguments of other types (conversion constructors).
If it can (ie. if the appropriate constructor is available), the compiler will treat both int a = 0; and int a(0) as a call to the copy constructor. The precise behavior is explained here.
I think this is because constructors with initializer lists are generally faster, which I think has to do with the the fact that the value can be placed into the newly allocated variable memory in fewer memory accessing operations. Here is a CPP FAQ on that topic (a great website for questions like this, btw).
Basically implicit is the preferred way:
int nValue = 5; // explicit initialization
int nValue(5); // implicit initialization
Here are some reads:
http://www.learncpp.com/cpp-tutorial/21-basic-addressing-and-variable-declaration/
Explicit Assignment vs Implicit Assignment
When you use the first, what you call C-type initialization, the variable will be written to twice, first the default value and second the assignment, as for the second case it will directly be set to the specified value. I think modern compilers optimize this for primitive types but for objects it could make quite a difference.
I've heard I can initialize a value using this syntax:
int foo = {5};
Also, I can do the same thing using even less code:
int foo{5};
Well, are there any advantages/disadvantages of using them? Is it a good practice, or maybe it's better to use standard: ?
int foo = 5;
The three examples you gave, are not quite the same. Uniform initialization (the ones with { }) does not allow narrowing conversions
int i = 5.0; // Fine, stores 5
int i{5.0}; // Won't compile!
int i = {5.0}; // Won't compile!
Furthermore, copy initializations (the ones with an =) do not allow explicit constructors.
The new C++11 feature uniform initialization and its cousin initializer-lists (which generalizes the brace initialization syntax to e.g. the standard containers) is a tricky animal with many quirks. The most vexing parse mentioned in the comments by #Praetorian is only one of them, tuples and multidimensional arrays are another pandora's box.