инициализация — идиома для инициализации класса C ++ до нуля

Рассмотрим следующий класс C ++:

struct Point
{
int x;
int y;

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

Второй конструктор полезен для создания Point с конкретными x а также y ценности. Первый существует, так что я могу по умолчанию построить Point, Тем не менее, для эффективности, это defaultЭд и не устанавливает x а также y в ноль. Если бы я хотел установить все члены на ноль, у меня мог бы быть другой конструктор:

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)? Каковы плюсы / минусы двух методов? Или есть другой лучший механизм для этого?

Редактировать: Обратите внимание, что этот простой класс был выбран для иллюстрации; в действительности может быть гораздо больше членов, которым необходимо учитывать определенные значения по умолчанию «Инициализирован».

4

Решение

Сделайте свою жизнь проще, создайте простые структуры данных, такие как эти агрегаты:

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
10

Другие решения

Наиболее распространенная практика, которую я вижу для этого, заключается в реализации конструктора без аргументов со списком инициализации, который содержит для каждого члена класса любое значение по умолчанию, которое вы хотите.

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

Причиной этого является то, что вы, вероятно, никогда не захотите создавать экземпляр объекта, не инициализируя членов каким-либо известным значением, поэтому вы на самом деле не хотите, чтобы этот конструктор по умолчанию существовал.

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
0