Consider the following C++ class:
struct Point
{
int x;
int y;
explicit Point() =default; // 1
explicit Point(int x_, int y_): x(x_), y(y_) { } // 2
};
The second constructor is useful for creating a Point
with specific x
and y
values. The first exists so that I can default construct a Point
. However, for efficiency, it is default
ed and does not set x
and y
to zero. If I did want to set all members to zero, I could have another constructor:
explicit Point(int val) : x(val), y(val) { } // 3
This way, I can choose to either default initialize the Point
, or initialize it with all members being set to zero:
Point p1; // Don't initialize members.
Point p2(0); // Initialize all members to zero.
The problem with the third constructor is that I can really pass any value, not just zero. For example:
Point p(1); // Both x and y set to 1! Is this the intent? If so,
// probably should have used Point p(1, 1) instead.
Another way would be to have a special type which represents a zero or default value and pass that to the constructor:
explicit Point(Default) : x(0), y(0) { } // 4
Where Default
can be defined simply as:
struct Default { };
Then, I can control when I want the Point
to be initialized with default values:
Point p1; // Don't initialize members.
Point p2(Default()); // Initialize members with default values.
Which method would be considered better, the method with the sentinel type Default
(no. 4), or the constructor which takes a single value and initializes all members to that value (no. 3)? What are the pros/cons of the two methods? Or is there another better mechanism to do this?
Edit: Please note that this simple class was chosen for illustration; in reality, there might be many more members which need specific default values to be considered "initialized".
Make your life easier, make simple data structs like this aggregates:
struct Point
{
int x;
int y;
};
Now you can use aggregate initialization:
Point p; // members uninitialized
Point p{}; // members set to 0
Point p{1,2}; // members set to 1,2