const强制转换为全局变量,程序崩溃(c++)
const cast to a global var and program crashed (C++)
int main()
{
const int maxint=100;//The program will crash if this line is put outside the main
int &msg=const_cast<int&>(maxint);
msg=200;
cout<<"max:"<<msg<<endl;
return 0;
}
如果将'const int maxint=100;'定义放在主函数中,则函数将运行正常,但如果放在主函数中,则会崩溃并弹出"Access Violation"错误消息。
有人说这是一种"未定义的行为",我想知道确切的答案,以及如何安全地使用const强制转换?
他们是正确的,这是未定义的行为。您不允许修改const
变量的值,这是抛弃某些东西的const
性的危险:您最好知道它不是真正的const
。
编译器,看到maxint
是const
,不应该修改,甚至不需要给它一个地址。如果它认为合适,它可以用100取代maxint
的所有用途。正如Matteo Italia指出的那样,它也可能只是将常量放入内存的只读部分,这可能就是你正在发生的事情。这就是为什么修改它会产生未定义的行为。
可以安全地丢弃变量的const
属性的唯一方法是,该变量实际上不是const
,而是将const
限定符添加到非const
变量中,如:
int f(const int& x) {
int& nonconst = const_cast<int&>(x);
++nonconst;
}
int blah = 523;
f(blah); // this is safe
const int constblah = 123;
f(constblah); // this is undefined behaviour
考虑这个示例,它可以完美地编译:
int f(const int& x) {
int& nonconst = const_cast<int&>(x);
++nonconst;
}
int main() {
f(4); // incrementing a number literal???
}
你可以看到使用const_cast
是非常危险的,因为实际上没有办法判断一个变量最初是否为const
。您应该尽可能避免使用const_cast
(对于函数,通过不接受const
参数)。
修改为const
的对象(可变成员除外)会导致未定义的行为(来自c++ 03标准):
7.1.5.1/4 "The cv-qualifiers"
除了任何被声明为可变的类成员(7.1.1)都可以被修改之外,在const对象的生命周期(3.8)内,任何修改const对象的尝试都会导致结果在未定义行为中。
以上未定义的行为在const_cast
:
5.2.11/7 "Const cast"
[注:根据对象的类型,写操作通过指针、左值或指向数据成员的指针转换const-qualifier68)的Const_cast可能会产生undefined行为(7.1.5.1)。)
所以,如果你有一个const
指针或引用指向一个实际上不是const
的对象,你可以写这个对象(通过抛掉常量),但如果对象实际上是const
,则不允许。
const
对象放在只读存储器中。但是,它并不一定要这样做,而且对于不会崩溃的测试代码来说,显然不需要这样做。
只允许丢弃已知而不是为const
的对象的constness。例如,一个接口可能通过使用const
指针或const
引用传递对象,但是你传入的对象不是const
,并且想要/需要修改它。在这种情况下,抛弃constness可能是正确的。
另一方面,抛弃一个一直是const
的对象的constness可能会让你陷入深深的麻烦:当访问这个对象时,特别是当向它写东西时,系统可能会导致各种奇怪的事情:行为没有定义(由c++标准),在特定的系统上,它可能会导致访问冲突(因为对象的地址被安排在只读区域)。
请注意,尽管有另一个响应,我看到const
对象需要获得一个地址分配,如果地址曾经以某种方式被占用和使用。在代码中,const_cast<int&>(maxint)
表达式本质上获得常量int的地址,该常量显然存储在标记为只读的内存区域中。您的代码片段的有趣之处在于,它就像显然工作,特别是在打开优化时:代码足够简单,编译器可以告诉更改的位置并没有真正使用,并且实际上没有尝试更改内存位置!在这种情况下,不会报告访问违规。这显然是在函数内部声明常量时的情况(尽管常量也可能位于通常不能标记为只读的堆栈上)。代码的另一个潜在结果是(与是否在函数内声明常量无关),它实际上被更改,有时读取为100,而在其他上下文中(以某种方式或另一种方式涉及地址)读取为200。
- 提升 ASIO Async_receive崩溃程序
- 类指针方法崩溃程序
- get_body来自 IHTMLDocument2 崩溃程序
- 是否有可能存在不会崩溃程序的内存问题
- 调试运行时出现奇怪的崩溃程序(Eclipse C++)
- 儿童对话框 - setWindowTexta或sendmessagea崩溃程序-MFC
- 顶点阵列GLFW崩溃C 程序
- 将值分配给Float数据类型崩溃程序
- OpenCV-将变量添加到类成员崩溃程序
- boost::interprocess::managed_shared_memory 崩溃程序
- 将枚举值分配给整数崩溃程序
- SDL 1.2 -> SDL 2.0(崩溃程序)
- 空析构函数崩溃程序:C++
- 冒泡排序崩溃程序c++
- Ofstream关闭崩溃程序
- 删除字符* 崩溃程序
- c++矢量擦除崩溃程序
- Lua_getglobal崩溃程序
- 通过Copy Constructor创建的e2打印崩溃程序
- RNG崩溃c++程序