C++11 使用指针修改 initializer_list 中的元素导致 SIGSEGV,为什么?

C++11 modifying elements in initializer_list using pointer caused SIGSEGV, why?

我正在使用 const_cast 修改 initializer_list 中的元素,如下所示:

#include <initializer_list>
int main()
{
    auto a1={1,2,3};
    auto a2=a1;//copy or reference?
    for(auto& e:a1)
    {
        int*p=const_cast<int*>(&e);
        ++(*p);
    }
    for(auto& e:a2)
        cout<<e;
    return 0;
}

不幸的是,在执行 ++(*p) 时,这个 g++4.9.2 编译程序抛出 SIGSEGV。 VC.

没有出现问题

为什么,我的程序有没有安全操作?请帮忙,谢谢。

正如 在您之前的问题中,initializer_list<T> 的基础数组由 const 对象组成。修改声明 const 的对象是 未定义的行为 。来自 [dcl.type.cv]:

Except that any class member declared mutable (7.1.1) can be modified, any attempt to modify a const object during its lifetime (3.8) results in undefined behavior.

未定义行为的一个可能实例是 SIGSEV,这是您从 gcc 中看到的。另一种可能的实例是代码工作,这就是您在 VC 中看到的。只是不要这样做。

修改最初声明的数据 const 是未定义的行为,并且初始化列表的内容总是 const.

在这种情况下,列表的内容似乎存储在 read-only 页面或类似页面中,您会遇到运行时错误。你很幸运:对于未定义的行为 任何事情 都可能发生。

写入 const 导致未定义行为的另一个经典示例是,当您在一行中修改某些内容,并在下一行读取它时,修改不会显示出来。发生这种情况是因为编译器可以假定任何 const-declared(未引用)数据 不会更改 ,因此它可以优化其代码以假定初始值始终是该值有。

编译器实际做的其他可能性是编译器注意到您在分支上执行未定义的行为,推理分支不能在逻辑上采用,推导出进入分支的条件 must 是另一个设置,并完全消除一个分支(and/or 进入一个前提条件由上述逻辑证明的分支)。未定义的行为可以进行时间旅行。

您的硬盘驱动器可能会被格式化,计算机可能会爆炸,它会将您的网络历史记录通过电子邮件发送到您的 parents:编译器可以自由地让代码在任何时候以任何理由或无理由执行任何操作.

不要做未定义的行为。