Значения элементов по умолчанию или параметры конструктора по умолчанию в структурах? - PullRequest
3 голосов
/ 25 октября 2019

В современном C ++ мне разрешено реализовать структуру со значениями элементов по умолчанию, т.е.

struct A
{
  int x = 5;
  float y = 1.0f;
};

, но я также могу создать структуру, которая не имеет «значений элементов по умолчанию», но может вызвать ее конструкторс параметрами по умолчанию, как в примере ниже:

struct B {
  int x;
  float y;

  B(int x_ = 5, float y_ = 1.0f) : x(x_), y(y_) {}
};

Что я хочу знать, есть ли какая-либо разница с точки зрения чистого кода или архитектуры между ними? А может, есть и другие, еще более важные отличия? В первом случае у меня меньше кода для написания, и я думаю, что я все еще могу построить объект, например A({2, 3.14f}), даже если конструктор не определен.

Какой ваш путь в проект и почему?

1 Ответ

4 голосов
/ 25 октября 2019

Не существует «правильного» способа выбрать форму инициализации, это зависит от конкретных ограничений / обстоятельств проекта или даже вашей личной пользы. Тем не менее, я думаю, что эти проблемы должны быть приняты во внимание при выборе инициализаторов за / против в классе.

  1. Pro : удобочитаемость. Когда вы хотите понять, для чего нужен класс, вы часто начинаете с его определения. При просмотре элементов данных вашему мозгу удобно, чтобы начальное значение каждого элемента данных было рядом с его типом, вместо сканирования, возможно, нескольких конструкторов.

  2. Pro: Добавление большего количества конструкторов намного проще, когда не требуется вставка копий инициализаторов другого существующего конструктора. Используя инициализаторы членов класса, вы с меньшей вероятностью забудете некоторую инициализацию при добавлении конструктора.

  3. Pro : удалить конструктор легко. Допустим, вы начинаете с нового класса, добавляете несколько функций-членов, конструктор и члены-данные. Затем вы вспоминаете, что сказал Скотт Мейерс в «Как функции, не являющиеся членами, улучшают инкапсуляцию», и решаете превратить функции-члены в бесплатные. Ваш тип теперь выглядит как тупой struct с некоторыми данными, упакованными вместе - и когда его конструктор не включает никакой бизнес-логики, вы можете захотеть превратить тип в агрегат: с помощью инициализаторов класса вы просто удаляете конструктор -готово.

  4. Против : всякий раз, когда вы используете инициализаторы класса, должен быть известен конкретный тип инициализируемого члена данных. Это может быть проблемой, когда рассматриваемое определение класса находится в заголовке (наиболее вероятно), время компиляции является проблемой (наиболее вероятно), рассматриваемый элемент данных имеет определение большого веса (иногда) и / или требует нетривиальные зависимости от конструкции (иногда). Простое указание может быть следующим: в сценарии, где Pimpl-идиома полезна, это важнее, чем пункты 1.-3. и превосходит инициализаторы в классе, поэтому перейдите к Pimpl.

Заключительное примечание: основные рекомендации рекомендуют использовать инициализаторы в классе в C.48 , срассуждение:

Явно указывает, что одно и то же значение предполагается использовать во всех конструкторах. Избегает повторения. Избегает проблем с обслуживанием. Это приводит к самому короткому и эффективному коду.

...