Передаваемые Локальные Переменные (C++)
я столкнулся с проблемой в моем изучении C++, где локальная переменная в функции передается в локальную переменную с тем же именем в другой функции, обе эти функции выполняются в main().
когда это выполните,
#include <iostream>
using namespace std;
void next();
void again();
int main()
{
int a = 2;
cout << a << endl;
next();
again();
return 0;
}
void next()
{
int a = 5;
cout << a << endl;
}
void again()
{
int a;
cout << a << endl;
}
выдает:
2
5
5
Я ожидал, что снова () скажет null или 0, так как " a "снова объявлен там, и все же, похоже, использует значение, которое" a " было назначено в next ().
почему next() передайте значение локальной переменной " a "в again (), если" a " объявлено в другой раз в again ()?
3 ответов
http://en.cppreference.com/w/cpp/language/ub
вы правы, неинициализированная переменная-это no-no. Однако вы можете объявить переменную и инициализировать ее только позже. Память выделена для хранения целого числа, но какое значение будет находиться в этой памяти, пока вы этого не сделаете, может быть чем угодно. Некоторые компиляторы автоматически инициализируют переменные в ненужные значения (чтобы помочь вам поймать ошибки), некоторые автоматически инициализируют значения по умолчанию, а некоторые совсем ничего. Сам на C++ ничего не обещает, следовательно, это неопределенное поведение. В вашем случае с вашей простой программой достаточно легко представить, как компилятор создал код сборки, который повторно использовал тот же самый кусок памяти, не изменяя его. Однако это слепая удача, и даже в вашей простой программе не гарантируется. Эти типы ошибок могут быть довольно коварными, поэтому сделайте это правилом: будьте бдительны к неинициализированным переменным.
неинициализированный неstatic
локальная переменная *встроенный тип (фух! это был полный рот) имеет неопределено значение. За исключением char
типы, используя это значение, формально дают Неопределенное Поведение, a.к. a. УБ. Все может случиться, включая поведение, которое вы видите.
по-видимому, с вашим компилятором и параметрами, область стека, которая использовалась для a
на next
, не было использовано для что-то еще до вызова again
, где он был использован для a
на again
, теперь с тем же значением, что и раньше.
но вы не можете полагаться на это. С UB все или ничего не может случиться.
* или вообще типа стручка,Простые Старые Данные. Спецификация этого стандарта несколько сложна. В C++11 он начинается с §8.5 / 11: "если для объекта не указан инициализатор, объект по умолчанию-инициализировано; если инициализация не выполняется, объект с автоматической или динамической длительностью хранения имеет неопределенное значение.". Где "автоматическая ... продолжительность хранения" включает случай локального не -static
переменной. И где "нет инициализации" может происходить двумя способами через §8.5/6, который определяет инициализацию по умолчанию, а именно либо через конструктор по умолчанию ничего не делать, либо через объект, не имеющий класса или типа массива.
Это совершенно случайное и неопределенное поведение.
произошло то, что у вас есть две функции, вызываемые сразу после друг друга. Оба будут иметь более или менее идентичные прологи функций, и оба зарезервируют переменную точно такого же размера в стеке.
поскольку в игре нет других переменных, и стек не изменяется между вызовами, вы просто оказываетесь с локальной переменной во второй функции "landing" в том же самом поместите как локальную переменную предыдущей функции.
очевидно, на это не стоит полагаться. На самом деле, это прекрасный пример того, почему вы должны всегда переменные инициализировать!