Это действительная функция? - PullRequest
13 голосов
/ 21 сентября 2011

Что происходит со ссылкой в ​​параметре функции, если она уничтожается при возврате из функции, то как const int *i остается действительным указателем?

const int* func(const int &x = 5)
{
    return &x;
}


int main()
{
    const int *i = func();
}

Ответы [ 7 ]

8 голосов
/ 21 сентября 2011

§12.2 / 5:

«Временная граница с опорным параметром в вызове функции (5.2.2) сохраняется до завершения полного выражения, содержащего вызов.»

Это означает, что при инициализации i он получает адрес временного объекта, который существует в этой точке. Однако, как только i инициализируется, временный объект будет уничтожен, а i станет просто еще одним висящим указателем.

Как таковая, да, функция действительна - но с окружающим кодом, в котором вы ее написали, любой код, который вы добавили впоследствии и попытался разыменовать i, дал бы неопределенное поведение.

3 голосов
/ 21 сентября 2011

Тот факт, что указатель имеет значение, не означает, что он является действительным указателем.

В этом случае он содержит адрес, который раньше был адресом x, и есть вероятность, что адрес все еще имеет значение 5, но это недопустимый указатель, и вы не можете рассчитывать, что это значение будет там.

1 голос
/ 21 сентября 2011

Я думаю, что x создается как неназванный временный элемент в стеке при настройке вызова на func(). Этот временный объект будет существовать по крайней мере до конца оператора в вызывающей стороне. Таким образом, int* i совершенно правильно. Он перестает быть действительным только в конце утверждения - это означает, что вы не можете его использовать.

В стандарте есть что-то о том, что неназванные временные ссылки сохраняются до тех пор, пока последняя ссылка на них не выйдет из области видимости, но я не думаю, что она охватывает эту явную и скрытую косвенность. [Рад, что кто-то сказал мне иначе.]

1 голос
/ 21 сентября 2011

переменная "i" по-прежнему является указателем, но даже чтение значения, на которое она указывает, даст вам неопределенное поведение. Вот почему вы никогда не должны писать такую ​​функцию, как func.

1 голос
/ 21 сентября 2011

int i указывает на участок памяти, доступ к которому небезопасен, это недопустимый указатель.

0 голосов
/ 21 сентября 2011

Аргументы по умолчанию оцениваются каждый раз, когда вызывается функция, поэтому вызов func() на самом деле func(5), который привязывает временный объект к ссылке на const. Время жизни этого временного затем продлевается до конца функции и объект уничтожается. Любой указатель на этот объект после этого недопустим, а разыменование - неопределенное поведение.

0 голосов
/ 21 сентября 2011

5 - данные программы.Он находится в сегменте данных, а не в стеке или куче.

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

...