Последствия отказа в присвоении возвращаемого значения функции переменной - PullRequest
0 голосов
/ 23 ноября 2018

Я выполняю некоторые вводные упражнения C ++, одно из которых: Что будет на экране после выполнения этого кода:

int& testMethod (int& a){

    int c = a+a;
    return c;
};

int main() {
    int z = 5;
    int* y = new int (testMethod(z));
    int r = 25;
    testMethod(r);
    std::cout<<*y;
    return 0;
}

Мои вопросы:

  1. Прав ли я, что это пример UB, поскольку значение, возвращаемое testMethod при втором вызове, не присваивается переменной?
  2. Верно ли, что возвращаемое значение, хотя и не присвоенопеременная, все еще может быть восстановлена, но это зависит?

Для № 2, я просто пытаюсь подтвердить свое понимание того, как работает стек, что выглядит следующим образом.Когда функция возвращает значение и значение присваивается переменной, результат вычислений сначала сохраняется в стеке как retval в некоторой ячейке памяти, а затем присваивается переменной, то есть записывается в другую ячейку памяти.Затем указатель стека перемещается вверх (опять же, насколько я понимаю, «верх» стека на самом деле является его «дном», когда указатель перемещается от самого большого адреса к наименьшему).Но retval все еще существует некоторое время, пока не будет перезаписан другим фрагментом данных (что может произойти почти мгновенно).

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

Ответы [ 2 ]

0 голосов
/ 23 ноября 2018

То, как автоматическое распределение реализовано на вашей конкретной платформе, не имеет значения.Ваши коды вызывают срабатывания UB не потому, что вы игнорируете возвращаемое значение testMethod (которое, кстати, является не методом), а наоборот, потому что в следующей строке используетсяit:

int* y = new int (testMethod(z));

Проблема в том, что testMethod всегда возвращает висячую ссылку на то, что было его локальной переменной c.Использование этой ссылки для инициализации динамически распределяемых триггеров int UB.

Как и ожидалось, включение предупреждений (что вы всегда должны делать) приводит к следующему:

warning: reference to stack memory associated with local variable 'c' returned [-Wreturn-stack-address]
0 голосов
/ 23 ноября 2018

Прав ли я, что это пример UB, поскольку значение, возвращаемое testMethod при втором вызове, не присваивается переменной?

Может быть, вы еще не заметили, ноВы игнорируете возвращаемое значение все время (небрежно говоря).Например, std::cout << *y; возвращает ссылку на std::cout, в противном случае вы не можете связать ее, как в

std::cout << "hello" << "world";

Нет.Игнорирование возвращенного значения не является неопределенным.Иногда вы не можете игнорировать возвращаемое значение (просто другой пример: присваивание обычно возвращает ссылку, то есть вы можете написать a = b = c;, но обычно вы просто пишете b = c; a = b;).

Для 2) вы слишком многоучитывая детали реализации.Не переусердствуйте.Вы игнорируете значение, вот и все.

PS: ваш код имеет UB, но по совершенно другой причине (см. другой ответ ).

...