Я бы просто добавил немного больше деталей. Базовый массив 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
.