В общем смысле,
инициализация может быть выполнена тремя основными способами.
std::initializer_list
участвует в двух из трех.
Foo bar = {...};
Foo bar{...};
В обоих случаях выполняется
List Initialization, в первом - copy list-initialization, во втором - direct list-initialiaztion.
Тут важно отметить что принятие решения о использовании
std::initializer_list
выполняются только на этапе трансляции. В обоих случаях сперва транслятор попробует придумать
std::initializer_list
. Если у аргументов типы разные (а приведение типов при такой записи не делается), то попробовать создать
std::initializer_list
у транслятора не получится. Но если получилось, то транслятор уже итак знает число аргументов, переданных в конструктор.
Образно выражаясь, транслятор прямо перед вызовом конструктора объекта оформляет короткую область видимости, в рамках которой оформляется локальный массив неизменной длины. В этот локальный массив по своему значению складываются аргументы конструктора, далее этот массив обрамляется в
std::initializer_list
, с которым конструктор и вызывается.
Сразу по завершении конструктора локальная область видимости закрывается и память массива аргументов конструктора освобождается. Поэтому
std::initializer_list
нельзя копировать, перемещать, сохранять в состоянии конструируемого объекта.
std::initializer_list
не владеет отображаемой памятью, он только дает к ней доступ.