将 C++ class 初始化为零的习语

Idiom to initialize C++ class to zero

考虑以下 C++ class:

struct Point
{
    int x;
    int y;

    explicit Point() =default; // 1
    explicit Point(int x_, int y_): x(x_), y(y_) { } // 2
};

第二个构造函数可用于创建具有特定 xy 值的 Point。第一个存在,以便我可以默认构造一个 Point。但是,为了效率,它被 defaulted 并且不会将 xy 设置为零。如果我确实想将所有成员设置为零,我可以有另一个构造函数:

explicit Point(int val) : x(val), y(val) { } // 3

这样,我可以选择默认初始化 Point,或者将其初始化为所有成员都设置为零:

Point p1;    // Don't initialize members.
Point p2(0); // Initialize all members to zero.

第三个构造函数的问题是我真的可以传递任何值,而不仅仅是零。例如:

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.

另一种方法是使用一个表示零值或默认值的特殊类型,并将其传递给构造函数:

explicit Point(Default) : x(0), y(0) { } // 4

其中 Default 可以简单定义为:

struct Default { };

然后,我可以控制何时使用默认值初始化 Point

Point p1;            // Don't initialize members.
Point p2(Default()); // Initialize members with default values.

哪种方法会被认为更好,标记类型 Default 的方法(第 4 项),还是采用单个值并将所有成员初始化为该值的构造函数(第 3 项)?两种方法的pros/cons是什么?还是有其他更好的机制来做到这一点?

编辑: 请注意,选择这个简单的 class 是为了说明;实际上,可能有更多的成员需要考虑特定的默认值 "initialized"

我看到的最常见的做法是使用初始化列表实现无参数构造函数,该初始化列表包含 class 的每个成员设置为您想要的任何默认值。

Point(): x(0), y(0) { }

这背后的原因是,您可能永远不想在未将成员初始化为某个已知值的情况下实例化对象,因此您实际上不希望存在默认构造函数。

让您的生活更轻松,制作像这样的简单数据结构聚合:

struct Point
{
    int x;
    int y;
};

现在可以使用聚合初始化了:

Point p;      // members uninitialized
Point p{};    // members set to 0
Point p{1,2}; // members set to 1,2

另一种选择是使用:

struct Point
{
    int x;
    int y;

    explicit Point(int x_ = 0, int y_ = 0): x(x_), y(y_) {}
};

Point p1;        // 0, 0
Point p2(1);     // 1, 0
Point p3(1, 10); // 1, 10