Учтите следующее:
struct X {
X() {}
X(X&&) { puts("move"); }
};
X x = X();
В C ++ 14 перемещение можно было опустить, несмотря на то, что конструктор перемещения имеет побочные эффекты благодаря [class.copy] / 31,
Это исключение операций копирования / перемещения ... разрешено в следующих обстоятельствах ... когда временный объект класса, который не был привязан к ссылке (12.2), будет скопирован / перемещен в объект класса с тем же cv-unqualified тип
В C ++ 17 этот пункт был удален. Вместо этого перемещение гарантированно будет пропущено благодаря [dcl.init] /17.6.1:
Если выражение инициализатора является prvalue, а cv-неквалифицированная версия исходного типа является тем же классом, что и класс назначения, выражение инициализатора используется для инициализации целевого объекта. [Пример:
T x = T(T(T()));
вызываетT
конструктор по умолчанию для инициализацииx
. - конечный пример]
Пока что факты, о которых я говорил, хорошо известны. Но теперь давайте изменим код так, чтобы он читался так:
X x({});
В C ++ 14 выполняется разрешение перегрузки, и {}
преобразуется во временный тип X
с использованием конструктора по умолчанию, а затем перемещается в x
. Правила исключения копий позволяют опустить этот ход.
В C ++ 17 разрешение перегрузки такое же, но теперь [dcl.init] /17.6.1 не применяется, и маркера из C ++ 14 больше нет. Выражения инициализатора не существует, поскольку инициализатор - это список инициализации в фигурных скобках. Вместо этого похоже, что применяется [dcl.init] / (17.6.2):
В противном случае, если инициализация является прямой инициализацией, или если это инициализация копированием, где cv-неквалифицированная версия исходного типа является тем же классом, что и класс назначения, или производным классом, рассматриваются конструкторы. Применимые конструкторы перечислены (16.3.1.3), и лучший из них выбирается посредством разрешения перегрузки (16.3). Выбранный таким образом конструктор вызывается для инициализации объекта с выражением инициализатора или списком выражений в качестве аргумента (ов). Если конструктор не применяется или разрешение перегрузки неоднозначно, инициализация сформирована неправильно.
Похоже, что для этого требуется вызов конструктора перемещения, и если где-то в стандарте есть правило, в котором говорится, что его можно исключить, я не знаю, где он находится.
{}
преобразуется во временный объект типа _2 _..., который затем привязывается к ссылке из конструктора перемещения. Я не думаю, что ваша первоначальная цитата применима. - person Barry   schedule 08.02.2018X
{}
иX&&
временнымX
(или{}
, опять же ласковой формулировкой). Возможно, нигде нетX
, инициализированного временным элементом. - person Johannes Schaub - litb   schedule 01.03.2018