Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Semantic difference in C++, defining a constant data instance

Tags:

c++

syntax

c++11

Do the following four different syntax do the same thing when initializing a constant data member, of type int for example, in C++ 11? If not, what is the difference?

{
    const int a = 5; //usual initialization, "=" is not assignment operator here it is an initialization operator.
}
{
    const int a(5); //calling the constructor function directly
}
{
    const int a = {5}; //similar to initializing an array
}
{
    const int a{5}; //it should work, but visual studio does not recognizing it
}

Why is the fourth one not recognized by Visual Studio as a valid statement?

like image 661
A_Matar Avatar asked Sep 01 '26 13:09

A_Matar


2 Answers

They are all valid and the same in Visual Studio 2013 (the last one is not valid in VS2012 as @remyabel suggested).

The two {...} syntaxes can differ from the others in what constructor is called for a type, but the type int uses no constructor.

They will differ when constructing a class that accepts a std::initializer_list<T>.

Take, for example, this constructor that has - in some form - always been a part of std::vector

explicit vector( size_type count ... );

And this one that was added in C++11

vector( std::initializer_list<T> init, const Allocator& alloc = Allocator() );

Here, vector<int>(5) will call the first constructor and make a vector size 5.

And vector<int>{5} will call the second and make a vector of a single 5.

like image 98
Drew Dormann Avatar answered Sep 05 '26 16:09

Drew Dormann


In C++03 these are equivalent

const int a = 3;
const int a(3);

In C++11 the uniform initialization syntax was introduced and thus

const int a{3};
const int a = {3};

are allowed and are equivalent. However, the first two and the second two are NOT equivalent in all cases. {} doesn't allow narrowing. For example

int abc = {12.3f};
int xyz(12.3f);

Here's what GCC says

error: type 'float' cannot be narrowed to 'int' in initializer list [-Wc++11-narrowing]

int abc = {12.3f};
           ^~~~~

warning: implicit conversion from 'float' to 'int' changes value from 12.3 to 12 [-Wliteral-conversion]

int abc = {12.3f};
          ~^~~~~

So the former begot an error, while the latter, just a warning.

Caveats in the uniform initialization syntax: If a was an object of a type accepting std::initializer_list, then const MyClass a = { 1 } would mean you're using that constructor and not the constructor taking a single int even if it was available (explained in Drew's anwer); If you want to choose the other constructor, then you've to use the () syntax. If a was an array, then you're using aggregate initialization.

See here for various initialization options available in C++.

like image 26
legends2k Avatar answered Sep 05 '26 16:09

legends2k