改变 volatile const 的值 - G++ vs Visual Studio 2019

Changing value of volatile const - G++ vs Visual Studio 2019

所以我有以下片段(背后有一个很好的理由):

#include <iostream>

volatile const float A = 10;

int main() {
    volatile const float* ptr = &A;
    float* safePtr = const_cast<float*>(ptr);
    *safePtr = 20;

    std::cout << A << std::endl;

    return 0;
}

在 G++ v8.2.0(来自 MinGW 套件)下,该程序可以正常编译并按预期输出 20。在 VS2019 下,它编译,但抛出运行时异常 - Exception thrown at 0x00007FF7AB961478 in Sandbox.exe: 0xC0000005: Access violation writing location 0x00007FF7AB969C58.

有没有办法让 VS2019 的行为与 G++ 的行为相同?以及如何使用 CMake 实现?

以下所有标准参考均指N4659: March 2017 post-Kona working draft/C++17 DIS.


根据 [dcl.type.cv]/4,您的程序有未定义的行为

Except that any class member declared mutable can be modified, any attempt to modify a const object during its lifetime results in undefined behavior. [ Example:

// ...

const int* ciq = new const int (3);  // initialized as required
int* iq = const_cast<int*>(ciq);     // cast required
*iq = 4;                             // undefined: modifies a const object

因此,demons may fly out of your nose 以及超出这一点的任何类型的程序分析,包括比较不同编译器的行为,都将是徒劳的。

你的问题很有趣,似乎 const_cast 允许更改底层 const 对象,这确实很好,但不幸的是不, const 对象不能以任何方式安全更改,即使它看起来正在工作。

const_cast makes it possible to form a reference or pointer to non-const type that is actually referring to a const object or a reference or pointer to non-volatile type that is actually referring to a volatile object. Modifying a const object through a non-const access path and referring to a volatile object through a non-volatile glvalue results in undefined behavior.

你不应该试图通过忽略这个问题来解决这个问题,我的猜测是你在 VS 中以调试模式 运行 调试程序,所以它可以捕获 g++ 没有捕获到的错误,但是如果你 运行 你的程序通过调试器你可能会看到同样的问题,尽管根据未定义行为的性质不能保证它。

要走的路是修复代码,而不是忽略问题。

如前所述,您不能合法地修改 const 对象...

但是你可以在 non-const 对象上有 const 引用:

因此您可以使用以下内容:

const float& A = *([]() { static float a = 10; return &a; }());
// const float& A = []() -> float& { static float a = 10; return a; }();


int main() {
    float* safePtr = const_cast<float*>(&A);
    *safePtr = 20;

    std::cout << A << std::endl;
}

(不需要volatile)。