Tuesday Coding Tip 05 - Object initialization in C++

posted Originally published at medium.com 2 min read

Tuesday coding tips are super short posts about various tidbits mainly from C++, but also from other programming languages I use. You can also follow the #TuesdayCodingTips hashtag on Mastodon and Linkedin.


There is a five-hundred-page book about C++ initialization out there. Why? Because we cater to way too many styles and many constructor capabilities. This tip is not about explaining all the options but rather about some good practices you can use to minimize mistakes.

The “classic” or pre-C++11 way of initializing objects has the pitfall of triggering the “most vexing parse”. In such case, the compiler cannot tell whether you are calling a constructor or making a function declaration. And because C allowed for function declaration inside functions, it will pick the function declaration. You can omit the braces for the default constructor, but you can still encounter problems as shown in the ‘mvp2’ case. Trunk versions of GCC and Clang emit a helpful warning in this case.

// Classic C++ style
Object obj1(param1, param2); // This works
Object mvp1(); // Most Vexing Parse
Object mvp2(int(param1), int(param2)); // Also MVP

The “modern”, “universal” or post-C++11 way is also not the best one. It is consistent with struct initialization but can invoke incorrect constructors if you intermix normal parameters and std::initializer_list as demonstrated with the std::vector.

// Modern (uniform) C++ style
Object obj2{param1, param2};
Object obj2_2 = {param1, param2};
std::vector<int> vec(10); // vector containing ten default constructed items
std::vector<int> vec{10}; // vector containing one element with value 10

Then you have what I call a “Java” style. It’s verbose and has the same issues if you use curly braces. At least it doesn’t trigger MVP. The last version is what I often use due to its similarity to many other languages where you use var or let to denote the variables and usually specify the type name after the variable name.

// Verbose Java style
Object obj3 = Object(param1, param2);
Object obj3_2 = Object{param1, param2};

// Modern language style
auto obj4 = Object(param1, param2);
auto obj4_2 = Object{param1, param2};

Note that even though there is an assignment operator, no assignment, copy or move is happening — objects are constructed directly.

I recommend using the “modern language style” with simple braces only for regular constructors and curly braces only for initializer-list constructors. It makes your intent clear and prevents you from accidentally shooting yourself in the foot. “Java style” might be preferable for class attribute declarations, with the same rules regarding braces.

More on the subject:

1 Comment

0 votes

More Posts

Tuesday Coding Tip 06 - Explicit template instantiation

Jakub Neruda - Apr 7

Tuesday Coding Tip 02 - Template with type-specific API

Jakub Neruda - Mar 10

Tuesday Coding Tip 08 — Explicit template specialization

Jakub Neruda - Apr 21

Tuesday Coding Tip 01 - C++ Concepts

Jakub Neruda - Mar 3

Tuesday Coding Tip 10— CTest

Jakub Neruda - May 5
chevron_left

Related Jobs

Commenters (This Week)

1 comment
1 comment

Contribute meaningful comments to climb the leaderboard and earn badges!