Подтвердить что ты не робот

Является ли "переупорядочивание" ссылок на С++ подобным законным?

Является ли следующий законным в С++?

Насколько я могу судить, Reference имеет тривиальный деструктор, поэтому он должен быть законным.
Но я думал, что ссылки не могут быть восстановлены на законных основаниях... могут ли они?

template<class T>
struct Reference
{
    T &r;
    Reference(T &r) : r(r) { }
};

int main()
{
    int x = 5, y = 6;
    Reference<int> r(x);
    new (&r) Reference<int>(y);
}
4b9b3361

Ответ 1

Я думаю, что нашел ответ в отрывке ниже "цитируемого", в котором говорится о тривиальных побочных эффектах dtor/dtor, а именно [basic.life]/7:

Если после того, как срок жизни объекта закончился и перед хранилищем, которое объект занят повторно используется или выпущен, создается новый объект в месте хранения, в котором был загружен исходный объект, указатель, указывающий на исходный объект, ссылка, относящаяся к исходному объекту, или имя исходного объекта будет автоматически ссылаться на новый объект и, как только время жизни нового объекта запустится, может использовать для управления новым объектом, если:

  • хранилище для нового объекта точно накладывает место хранения, в котором находился исходный объект, и

  • новый объект имеет тот же тип, что и исходный объект (игнорируя cv-квалификаторы верхнего уровня) и

  • тип исходного объекта не является константным и, если тип класса, не содержит нестатического элемента данных, тип которого является const-квалифицированным или ссылочным, и

  • исходный объект был самым производным объектом типа T, а новый объект является наиболее производным объектом типа T (то есть они не являются подобъектами базового класса).

Повторно используя хранилище, мы заканчиваем срок службы исходного объекта [basic.life]/1

Время жизни объекта типа T заканчивается, когда:

  • if T - это тип класса с нетривиальным деструктором, начинается вызов деструктора или

  • хранилище, которое объект занимает, повторно используется или освобождается.

Итак, я думаю, что [basic.life]/7 охватывает ситуацию

Reference<int> r(x);
new (&r) Reference<int>(y);

где мы заканчиваем время жизни объекта, обозначенного r, и создаем новый объект в том же месте.

Поскольку Reference<int> - это тип класса с ссылочным элементом данных, требования [basic.life]/7 выполняются не. То есть r может даже не ссылаться на новый объект, и мы не можем использовать его для "манипулирования" этим вновь созданным объектом (я интерпретирую это "манипулирование" также как доступ для чтения).

Ответ 2

Вы не переплетаете ссылку, вы создаете новый объект в памяти другого с новым местом размещения. Поскольку деструктор старого объекта никогда не запускался, я думаю, что это будет поведение undefined.

Ответ 3

В вашем примере ссылка не восстанавливается. Первая ссылка (построенная по строке 2 с именем r.r) привязана к int, обозначенному x для всего его времени жизни. Это базовое время жизни заканчивается, когда хранилище для его содержащего объекта повторно используется путем размещения нового выражения в третьей строке. Объект замены содержит ссылку, которая привязана к y для всего ее времени жизни, которая длится до конца ее области - конец main.