Ответ 1
Инициализация списка, когда используется для инициализации ссылки, примет перечисленные значения и преобразует их в prvalue (aka: временный), который будет использоваться для прямой инициализации ссылки.
Итак, int &b{foo{}}
функционально эквивалентно int &b(int(foo{}))
. Это неоднозначно; он может генерировать int
через operator int
или operator int&
.
Но даже если бы это не было двусмысленным, вы все равно получали бы ссылку на константу без знака. Это незаконно. Поэтому этот код никогда не срабатывал.
Брексированные-init-списки (фигурные скобки) инициализируют объекты, а не ссылки на объекты. Если у вас уже есть объект и вы хотите получить ссылку на него, не используйте скопированные init-списки.
Но в этом случае почему компилятор принимает # 5?
Поскольку инициализация списка представляет собой ряд правил с приоритетом. Правило, которое имеет более высокий приоритет, чем тот, который я указал выше, относится к списку с привязкой-инициализацией, который содержит одно значение, тип которого идентичен типу инициализации. # 5 и 6 просто так соответствуют этому счету, так как d
, e
и a
- все int&
s.
Но если вы просто возьмете мой совет и не будете использовать braced-init-lists, когда вы не пытаетесь создать объект, вам не придется беспокоиться о подобных случаях.