#include <iostream>
using namespace std;
int main() {
const int N = 22;
int * pN = const_cast<int*>(&N);
*pN = 33;
cout << N << '\t' << &N << endl;
cout << *pN << '\t' << pN << endl;
}
22 0x22ff74
33 0x22ff74
为什么同一地址有两个不同的值?
答案 0 :(得分:21)
为什么同一地址有两个不同的数据?
没有。允许编译器优化对const的任何提及,就好像你已经在其中编写了编译时值。
请注意,编译器也可以生成代码,当你运行它时会擦除你的硬盘,如果你做了一些讨厌的技巧,比如写入为consts保留的内存。
答案 1 :(得分:10)
您在行*pN = 33;
上获得了未定义的行为,因为您正在修改const值。任何事情都可能发生。不要这样做。
但是,很可能,您的编译器只是进行了优化。在该行:
cout << N << '\t' << &N << endl;
它知道N
是一个值为22的常量表达式,所以只需将该行更改为:
cout << 22 << '\t' << &N << endl;
在下一行中,您将获取N
地址的值,您将其“设置”为33。(但实际上,您所做的只是删除了有关程序状态的任何保证。)
答案 2 :(得分:5)
通过声明N
是const,您承诺不会修改它。然后你去修改它。这打破了编译器所做的一个假设,因此,程序行为不正确。
这被称为“未定义的行为” - 在违反语言假设后,程序的行为完全未定义。它不需要产生那个输出 - 它可以为两者产生33
,或者42
,或者崩溃,或者擦除你的硬盘驱动器,或通过你的鼻腔传唤召唤恶魔。所以,不要修改const值:)
答案 3 :(得分:3)
int * pN = const_cast<int*>(&N);
*pN = 33;
您的代码调用未定义的行为 1 ,因为您正在修改const
限定变量/对象的内容。
<子> 1) 未定义的行为:行为,例如在使用时可能出现的行为 错误的程序构造或错误的数据,其中 标准没有要求。[注意:允许的未定义行为 范围从完全忽略情况与不可预测 结果,在翻译或程序执行期间表现 记录的环境特征(有或没有 发布诊断消息),终止翻译 或执行(发出诊断信息)。
答案 4 :(得分:0)
答案 5 :(得分:0)
您可以将N声明为volatile,以强制编译器从变量的内存位置获取当前值。
"aggs" : {
"names":{
"terms":{
"field":"commodity_line.keyword",
"include" : "3.*"
}
}
答案 6 :(得分:0)
我有相同的问题(Why am I not able to modify the contents of const int even with const_cast<int*>?)。我认为每个人都很好地回答了这个问题。只需添加编译器的程序集输出
这是我的原始代码
const int y = 7;
int* a = new int;
a = const_cast<int*>(&y);
*a = 8;
std::cout << (int)*(&y) << std::endl;
这是程序集输出
std::cout << (int)*(&y) << std::endl;
00381CB6 push offset std::endl<char,std::char_traits<char> > (03813C5h)
**00381CBB push 7**
00381CBD mov ecx,dword ptr [_imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A (03900ACh)]
00381CC3 call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (03900B8h)]
00381CC9 mov ecx,eax
00381CCB call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (03900BCh)]
因此,编译器将在编译期间将const变量替换为其实际值。