C++中的指针和常量问题不大

Little problem with pointers and constants in C++

本文关键字:问题 常量 指针 C++      更新时间:2023-10-16

你能向我解释一下这种行为吗?这里的代码:

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; 

问题是你对编译器撒谎,而编译器非常擅长对那些对他们撒谎的人进行报复。

具体来说,在这一行中,您告诉编译器MAX_AGE是可变的:

b = (int*)&MAX_AGE;

这是一个谎言,因为你宣布MAX_AGE是一个const.接下来发生的事情称为未定义行为 (UB(:编译器可以在代码触发 UB 后自由生成任何结果,包括完全无意义。

然而,在你的例子中,有一个很好的解释打印的内容:知道MAX_AGE90的另一个名称,编译器已经优化了打印90std::cout << MAX_AGE << std::endl;,而无需从内存中查找其值。

MAX_AGE声明为const int。使用 c 样式强制转换,您可以删除恒常性,然后继续修改常量值。这是 UB。

这是为什么这是 UB 的一个主要示例:由于MAX_AGE的恒定性,编译器知道它不会改变,因此可以用文字90替换它的所有出现。

const告诉编译器变量MAX_AGE应存储在内存中相应段的写保护区域中。 有了这些知识,编译器就可以避免重复读取相同的内存位置。换句话说,编译器可能会缓存常量值。这就是为什么您看到MAX_AGE显示原始值的原因。

无论如何,正如已经提到的,您不应该将编译器与您的实际意图混淆。如果您打算将变量存储在写保护区域中,则不应对其进行修改。