Ответ 1
Правила оценки
A a1 = B(); // (1) copy-initialization
A a2 = {B()}; // (2) copy-initialization
A a3{B()}; // (3) direct-initialization
исходит из [dcl.init]/17:
- Если инициализатор представляет собой (не заключенный в скобки) бит-init-list, объект или ссылка инициализируется списком (8.5.4).
- [...]
- Если тип назначения - тип класса (возможно, cv-qualit):
- Если инициализация является прямой инициализацией или если она является копией-инициализацией, где cv-unqualified версия типа источника - это тот же класс, что и производный класс класса, конструкторы. [...]
- В противном случае (то есть для остальных экземпляров копирования-инициализации) пользовательские последовательности преобразования который может преобразовать из типа источника в тип назначения или (когда функция преобразования ) к его производному классу перечислены, как описано в 13.3.1.4, и лучший из них выбирается с помощью разрешения перегрузки (13.3). [...] Результат вызова (который является временным для случая конструктора) затем используется для direct-initialize, в соответствии с вышеприведенными правилами, объект, который является местом назначения инициализации копирования. В некоторых случаях реализация разрешено исключать копирование, присущее этой прямой инициализации, путем создания промежуточный результат непосредственно в инициализированный объект; см. 12.2, 12.8.
Как для a2
, так и для a3
, инициализатор представляет собой бит-init-list, поэтому мы просто выполняем инициализацию списка. Это заканчивается вызовом конструктора B const&
.
Для a1
первая подпула не применяется - поскольку тип источника (B
) не является тем же или производным классом целевого типа (A
). Таким образом, мы переходим во вторую точку подпункта, которая включает в себя рассмотрение функций преобразования. Существует один (A(B const&)
), поэтому мы эффективно переписываем выражение
A a1_new{A{B{}}};
Теперь, как правило, эта дополнительная копия будет удалена. Но вы явно запрещаете это, поэтому код не может скомпилироваться.
Что касается почему дифференцирования? Я не знаю. Кажется, что копирование-инициализация должна быть просто синтаксическим сахаром для прямой инициализации. В большинстве случаев, в конце концов, это...