Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to use the brace-enclosed initializer?

In C++11, we have that new syntax for initializing classes which gives us a big number of possibilities how to initialize variables.

{ // Example 1   int b(1);   int a{1};   int c = 1;   int d = {1}; } { // Example 2   std::complex<double> b(3,4);   std::complex<double> a{3,4};   std::complex<double> c = {3,4};   auto d = std::complex<double>(3,4);   auto e = std::complex<double>{3,4}; } { // Example 3   std::string a(3,'x');   std::string b{3,'x'}; // oops } { // Example 4   std::function<int(int,int)> a(std::plus<int>());   std::function<int(int,int)> b{std::plus<int>()}; } { // Example 5   std::unique_ptr<int> a(new int(5));   std::unique_ptr<int> b{new int(5)}; } { // Example 6   std::locale::global(std::locale("")); // copied from 22.4.8.3   std::locale::global(std::locale{""}); } { // Example 7   std::default_random_engine a {}; // Stroustrup's FAQ   std::default_random_engine b; } { // Example 8   duration<long> a = 5; // Stroustrup's FAQ too   duration<long> b(5);   duration<long> c {5}; } 

For each variable I declare, I have to think which initializing syntax I should use and this slows my coding speed down. I'm sure that wasn't the intention of introducing the curly brackets.

When it comes to template code, changing the syntax can lead to different meanings, so going the right way is essential.

I wonder whether there is a universal guideline which syntax one should chose.

like image 812
helami Avatar asked Apr 02 '12 12:04

helami


People also ask

What is a braced init list?

a braced-init-list is used to list-initialize an object, where the corresponding constructor accepts an std::initializer_list parameter.

How does C compiler know where an array must be initialised?

compiler will set first array element to the value you've provided (0) and all others will be set to zero because it is a default value for omitted array elements.

What is uniform initialization in C++?

Uniform initialization is a feature in C++ 11 that allows the usage of a consistent syntax to initialize variables and objects ranging from primitive type to aggregates. In other words, it introduces brace-initialization that uses braces ({}) to enclose initializer values.


2 Answers

I think the following could be a good guideline:

  • If the (single) value you are initializing with is intended to be the exact value of the object, use copy (=) initialization (because then in case of error, you'll never accidentally invoke an explicit constructor, which generally interprets the provided value differently). In places where copy initialization is not available, see if brace initialization has the correct semantics, and if so, use that; otherwise use parenthesis initialization (if that is also not available, you're out of luck anyway).

  • If the values you are initializing with are a list of values to be stored in the object (like the elements of a vector/array, or real/imaginary part of a complex number), use curly braces initialization if available.

  • If the values you are initializing with are not values to be stored, but describe the intended value/state of the object, use parentheses. Examples are the size argument of a vector or the file name argument of an fstream.

like image 198
celtschk Avatar answered Oct 05 '22 22:10

celtschk


I am pretty sure there will never be a universal guideline. My approach is to use always curly braces remembering that

  1. Initializer list constructors take precedence over other constructors
  2. All standard library containers and std::basic_string have initializer list constructors.
  3. Curly brace initialization does not allow narrowing conversions.

So round and curly braces are not interchangeable. But knowing where they differ allows me to use curly over round bracket initialization in most cases (some of the cases where I can't are currently compiler bugs).

like image 31
juanchopanza Avatar answered Oct 05 '22 22:10

juanchopanza