Я бы просто добавил немного больше деталей. Базовый массив std::initializer_listведет себя примерно так же, как временные. Рассмотрим следующий класс:
struct X
{
X(int i) { std::cerr << "ctor\n"; }
~X() { std::cerr << "dtor\n"; }
};
и его использование в следующем коде:
std::pair<const X&, int> p(1, 2);
std::cerr << "barrier\n";
Распечатывает
ctor
dtor
barrier
поскольку в первой строке создается временный экземпляр типа X(путем преобразования конструктора из 1) и также уничтожается. Ссылка, хранящаяся в pзатем болтается.
Что касается std::initializer_list, если вы используете это так:
{
std::initializer_list<X> l { 1, 2 };
std::cerr << "barrier\n";
}
затем базовый (временный) массив существует до тех пор, пока не lзавершится. Поэтому на выходе получается:
ctor
ctor
barrier
dtor
dtor
Однако, если вы переключитесь на
std::pair<std::initializer_list<X>, int> l { {1}, 2 };
std::cerr << "barrier\n";
Выход снова
ctor
dtor
barrier
поскольку базовый (временный) массив существует только в первой строке. Разыменование указателя на элементы lзатем приводит к неопределенному поведению.
Живая демоверсия здесь .
std::pair.