Undefined поведение и временные

1) Является ли поведение undefined возвратом ссылки на временную, даже если эта ссылка не используется? Например, гарантируется ли эта программа "хорошим":

int& func()
{
    int i = 5;
    return i;
}

int main()
{
    func();

    cout << "good" << endl;
    return 0;
}

2) Является ли поведение undefined просто ссылкой на объект, который больше не существует, даже если эта ссылка не используется? Например, гарантируется ли эта программа "хорошим":

int main()
{
    int *j = new int();
    int &k = *j;
    delete j;

    cout << "good" << endl;
    return 0;
}

3) Совместимо ли это поведение undefined?

int& func()
{
    int i = 5;
    return i;
}

int main()
{
    int& p = func();

    cout << "good" << endl;
    return 0;
}

Ответы

Ответ 1

Я не вижу никаких правил, запрещающих случай 1 и 2, и я не могу найти соответствующий отчет о дефекте.

Все, что у нас есть в проекте стандарта С++, из раздела 8.3.2 [dcl.ref]:

[...] Ссылка должна быть инициализирована для ссылки на действительный объект или функция. [Примечание: в частности, нулевая ссылка не может существовать в четко определенной программе, поскольку единственный способ для создания такой ссылки было бы привязать ее к "объекту", полученному косвенным путем через нулевой указатель, который вызывает поведение undefined. [...]

который не применяется к случаю 1, поскольку мы не инициализируем ссылку и ни один случай 2, поскольку объект действителен, когда мы инициализируем ссылку.

Это, похоже, относится к случаю 3. Итак, что означает действительный объект, является предметом следующего отчета о дефекте. Отчет о дефектах, который охватывает эту тему, по-прежнему открыт, и поэтому мы можем только почувствовать текущее мышление, которое заключается в том, что это должно быть поведение undefined.

Если мы посмотрим на отчет о дефекте 453: ссылки могут привязываться только к "действительным" объектам, что касается того, что означает привязать ссылку к недопустимому объекту. В нынешней предлагаемой резолюции говорится:

[...] Если значение lvalue, к которому привязана ссылка, не обозначает ни существующий объект или функцию соответствующего типа (8.5.3 [dcl.init.ref]), ни область хранения подходящего размера и выравнивание, чтобы содержать объект ссылочного типа (1.8 [intro.object], 3.8 [basic.life], 3.9 [basic.types]), поведение undefined. [...]

Таким образом, мы можем сказать, что нынешнее мышление состоит в том, что это должно быть поведение undefined, но в настоящее время это дефект, и поэтому мы не можем точно сказать, пока этот отчет о дефекте не будет разрешен. Я бы ошибался на стороне осторожности и предполагал, что это поведение undefined.

Ответ 2

2) Является ли поведение undefined просто ссылкой на объект, который больше не существует, даже если эта ссылка не используется?

Нет. Правило, которое ссылки должны ссылаться на действительный объект, применяется, когда ссылка инициализируется. Это правило уже цитируется в комментариях: "Ссылка должна быть инициализирована для ссылки на действительный объект или функцию". Это правило не было нарушено в вашей программе, и нет никаких других ограничений на ссылки, требующие от них ссылки на действительные объекты или функции после инициализации.

В стандарте есть несколько примеров, связанных с оборванными ссылками, такими как [class.temporary] 5.4:

struct S { int mi; const std::pair<int,int>& mp; };
S a { 1, {2,3} };
S* p = new S{ 1, {2,3} };  // Creates dangling reference.

и не говорит для любого такого примера, что простое существование оборванной ссылки недействительно. Хотя это никогда явно не указано как разрешенное, отсутствие каких-либо правил, запрещающих его, достаточно, чтобы разрешить это.

1) Поведение undefined возвращает ссылку на временную, даже если эта ссылка не используется?

Нет. Построение результата (инициализация ссылки) происходит в контексте вызываемой функции. В вызываемой функции может быть даже дополнительный код, который запускается после построения результата: деструкторы для локальных объектов запускаются после завершения построения результата. Поскольку ссылка инициализируется действительным объектом, это точно так же, как ваш второй вопрос, это же правило все еще не было нарушено.

3) Совместимо ли это поведение undefined?

Да. В вашем примере p не инициализируется ссылкой на действительный объект или функцию. Как вы можете судить по комментариям к вашему вопросу, есть проблемы с формулировкой в ​​стандарте, но цель этого правила довольно четко заключается в том, что если он нарушен, поведение undefined.