Маленькая проблема с указателями и константами в C ++ - PullRequest
0 голосов
/ 11 февраля 2020

Можете ли вы объяснить мне это поведение, пожалуйста? Вот код:

int* b = new int;
const int MAX_AGE = 90;
b = (int*)&MAX_AGE;
std::cout << b << std::endl;
std::cout << &MAX_AGE << std::endl;
std::cout << *b << std::endl;
std::cout << MAX_AGE << std::endl;
std::cout << "........." << std::endl;
*b = 2; 
std::cout << *b << std::endl; // HERE I get 2, that's ok
std::cout << MAX_AGE << std::endl; // HERE I still get 90, why?
std::cout << b << std::endl; 
std::cout << &MAX_AGE << std::endl; 

Ответы [ 3 ]

5 голосов
/ 12 февраля 2020

Проблема в том, что вы солгали своему компилятору, и компиляторы довольно хорошо отомстили людям, которые им * ie.

В частности, в этой строке вы сказали компилятору, что MAX_AGE изменяемый:

b = (int*)&MAX_AGE;

Это все ie, потому что вы объявили MAX_AGE как const. То, что происходит дальше, называется неопределенным поведением (UB) : компилятор может выдавать любые результаты, включая полную чушь, после того, как ваш код запускает UB.

В вашем случае, однако, есть довольно хорошее объяснение того, что печатается: зная, что MAX_AGE - это другое имя для 90, компилятор оптимизировал std::cout << MAX_AGE << std::endl; для печати 90, не ища его значение из памяти.

3 голосов
/ 11 февраля 2020

MAX_AGE объявлено как const int. С помощью приведения типа c вы удаляете константность и затем продолжаете изменять значение констант. Это UB.

Это яркий пример того, почему это UB: из-за константности MAX_AGE компилятор знает, что он не изменится и, таким образом, может заменить все его вхождения на литерал 90.

0 голосов
/ 12 февраля 2020

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

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

...