const转换为全局var和程序崩溃(C++)

Ori*_*ood 2 c++ const-cast

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;
}
Run Code Online (Sandbox Code Playgroud)

如果'const int maxint = 100;',该函数将运行正常.定义被放在main函数内但崩溃并弹出一条错误消息,如果放在外面则说"Access Violation".

有人说这是某种"未定义的行为",我想知道确切的答案以及如何安全地使用const转换?

Set*_*gie 9

它们是正确的,它是未定义的行为.你不允许修改const变量的值,这样就有可能丢掉const某些东西:你最好知道它不是真的const.

编译器,看到maxintconst,应该永远不会被修改,甚至没有给它一个地址.maxint如果认为合适,它可以替换100的所有用途.另外,正如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
Run Code Online (Sandbox Code Playgroud)

想想这个完美编译的例子:

int f(const int& x) {
    int& nonconst = const_cast<int&>(x);

    ++nonconst;
}

int main() {
    f(4); // incrementing a number literal???
}
Run Code Online (Sandbox Code Playgroud)

您可以看到如何使用const_cast非常危险,因为无法实际判断变量是否最初const.你应该尽可能避免使用const_cast(使用函数,只是不接受const参数).

  • 我会说这里编译器为常量提供了一个地址,但是把它放到了一个只读段中. (3认同)
  • @OriginalWood未定义的行为只是 - undefined.它没有被定义为崩溃.它可以做任何事情,从工作到崩溃,再到火上浇油.在那种情况下,它恰好在工作中. (2认同)

Mic*_*urr 5

修改一个对象const(可变成员除外)会导致未定义的行为(来自C++ 03标准):

7.1.5.1/4"cv-qualifiers"

除了可以修改声明为mutable(7.1.1)的任何类成员之外,任何在其生命周期内修改const对象的尝试(3.8)都会导致未定义的行为.

上述未定义的行为在标准的部分中特别指出const_cast:

5.2.11/7"Const cast"

[注意:根据对象的类型,通过指针,左值或指向数据成员的指针的写入操作可能会产生未定义的行为(7.1.5.1).]

因此,如果你有一个const实际上不是对象的指针或引用const,你可以写入该对象(通过抛弃constness),但如果对象确实是,则不允许const.

例如,允许编译器将const对象放在只读存储中.它没有必要,显然不适用于没有崩溃的测试代码.