Я знаю, что разыменование указателя или итератора, указывающего на неинициализированную память, недопустимо.
Не совсем так. Само по себе косвенное обращение не является незаконным. Поведение не определено только в случае выполнения таких операций, как те, которые зависят от значения.
std::addressof
не обращается к значению указанного объекта. Требуется только его адрес. Это то, что разрешено для объектов до и после их жизни, пока их хранилище было выделено.
Даже если это не так из-за некоторых технических особенностей правил, реализация стандартной библиотеки не обязательно ограничивается правила языка.
Стандартные цитаты (последний проект):
[basi c .life]
До времени существования объекта был запущен, но после того, как хранилище, которое будет занимать объект, будет выделено ... любой указатель, представляющий адрес хранилища, в котором будет ... расположен объект, может быть использован, но только ограниченными способами. Информацию о строящемся или разрушающемся объекте см. В [class.cdtor]. В противном случае такой указатель относится к выделенной памяти ([basi c .st c .dynami c .allocation]), и использование указателя, как если бы указатель имел тип void *, четко определено. Косвенное обращение через такой указатель разрешено , но результирующее lvalue может использоваться только ограниченными способами, как описано ниже. Программа имеет неопределенное поведение, если: (здесь нет подходящих случаев)
Точно так же до начала жизненного цикла объекта, но после того, как было выделено хранилище, которое объект будет занимать. . любое значение glvalue, которое относится к исходному объекту, может использоваться, но только ограниченным образом. Информацию о строящемся или разрушающемся объекте см. В [class.cdtor]. В противном случае такое glvalue относится к выделенному хранилищу ([basi c .st c .dynami c .allocation]), а с использованием свойств glvalue, которые не зависят от его значения, хорошо - определено . Программа имеет неопределенное поведение, если: (здесь нет подходящих случаев)