In modern C++ I am allowed to implement a struct with default member values i.e.
struct A
{
int x = 5;
float y = 1.0f;
};
but I can also do create a structure that has no "default member values" but can its constructor can be called with default parameters, as in the example below:
struct B {
int x;
float y;
B(int x_ = 5, float y_ = 1.0f) : x(x_), y(y_) {}
};
What I want to know is whether there is any difference from the clean code or architecture point of view between those? Or maybe there are another, even more important differences? In the first case, I've got less amount of code to write and I believe I can still construct the object like A({2, 3.14f}) even if the constructor is not defined.
Which would be your way to go in a project and why?
There is no "right" way do choose a form of initialization, it depends on the specific constraints/circumstances of a project or even your personal favor. However, I think those issues should be taken into account when deciding pro/contra in-class initializers.
Pro: Readability. When you want to understand what a class is good for, you often start off with its definition. When going through the data members, it's comfortable for your brain to have the initial value of each data member right next to its type, instead of scanning possibly multiple constructors.
Pro: Adding more constructors is much easier when no copy-pasting of the initializers of another existing constructor is required. With in-class member initializers, you are less likely to forget some initialization when adding a constructor.
Pro: Removing a constructor is easy. Let's say you start with a new class, add a bunch of member functions, a constructor and data members. Then you remember what Scott Meyers said in "How Non-Member Functions Improve Encapsulation" and you decide to turn the member functions into free ones. Your type now looks like a dumb struct with some data packed together - and when its constructor doesn't involve any business logic, you might want to turn the type into an aggregate: with in class initializers, you just remove the constructor - done.
Contra: Whenever you go with in class initializers, the concrete type of the data member being initialized must be known. This can be in issue when the class definition in question is in a header (most likely), compile times are an issue (most likely), the data member in question has a heavy-weight definition (sometimes) and/or requires non-trivial dependencies upon construction (sometimes). A simple guideline could be: in a scenario where the Pimpl-idiom is helpful, it's more important than points 1.-3. and does outrule in-class initializers, so go with Pimpl then.
Final note: the core guidelines recommend using in-class initializers in C.48, with the reasoning:
Makes it explicit that the same value is expected to be used in all constructors. Avoids repetition. Avoids maintenance problems. It leads to the shortest and most efficient code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With