Инициализация: T x (значение) против T x = значение, когда значение имеет тип T - PullRequest
2 голосов
/ 29 ноября 2009

T x (значение) обычно является лучшим выбором, поскольку он будет непосредственно инициализировать x значением, тогда как T x = value может создавать временное значение в зависимости от типа значения. Однако в особом случае, когда значение имеет тип T, я предполагаю, что выражение T x = value будет всегда в результате ровно одного вызова конструктора копирования. Я прав?

Я задал этот вопрос, потому что начинаю думать, что первый синтаксис слишком уродлив и труден для понимания, особенно когда значение является результатом вызова функции. например:

  • const std::string path(attributes.data(pathAttrib));
  • const std::string path = attributes.data(pathAttrib);

Ответы [ 2 ]

5 голосов
/ 29 ноября 2009

T x(value) обычно является лучшим выбором, потому что он непосредственно инициализирует x значением, тогда как T x = value может создать временное в зависимости от типа значения.

Вы почти правы, лучший выбор - самый ясный синтаксис. Вот как они различаются:

Форма инициализации (с использованием скобок или =), как правило, незначительна, но имеет значение, когда инициализируемая сущность имеет тип класса ... [8.5 / 11]

struct A {
  A(int) {}
};
struct B {
  explicit B(int) {}
};

int main() {
  { A obj (42); } // succeeds
  { A obj = 42; } // succeeds

  { B obj (42); } // succeeds
  { B obj = 42; } // fails
}

Требуется неявное преобразование, поэтому такие вещи, как vector<int> v = 3; терпят неудачу, но это выглядит неправильно в любом случае, верно? Любая копия скорее всего elided . Я не помню, чтобы это было узким местом во всем, что я написал, и я давно перестал беспокоиться об этом: просто используйте самый ясный синтаксис.


Хотя в особом случае, когда значение имеет тип T, я предполагаю, что выражение T x = value всегда будет приводить к точно одному вызову конструктора копирования. Я прав?

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

1 голос
/ 29 ноября 2009

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

В этих случаях дополнительное временное использование не допускается.

Ни одна из форм инициализации не препятствует выполнению оптимизаций, описанных в 12.8 [class.copy]. Хотя это ненормативный пример, в примере из 12.8 / 15 используется форма инициализации копирования инициализатора, чтобы продемонстрировать исключение двух копий в результате функции, возвращающей локальную переменную по значению инициализатору объекта. Это означает, что если value в вашем примере является временным типом T, то оно - и операция копирования в x - могут быть исключены.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...