问题描述
因此,我有以下代码段(及其背后的充分理由):
_
在G ++ v8.2.0(来自MinGW套件)下,该程序可以正常编译并按预期输出#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;
}
。在VS2019下,它可以编译,但会引发运行时异常-20
。
是否有办法使VS2019的行为与G ++相同?以及如何使用CMake?
解决方法
以下所有标准参考文献均引用N4659: March 2017 post-Kona working draft/C++17 DIS。
根据[dcl.type.cv]/4的规定,您的程序具有未定义的行为
除了任何声明为可变的类成员都可以修改之外,在其生存期内修改const对象的任何尝试都会导致未定义的行为。 [示例:
// ... 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
使得可以形成实际上指向const对象的非const类型的引用或指针,或者实际上指向易失性对象的非volatile类型的引用或指针。 通过非const访问路径修改const对象,并通过非易失性glvalue引用易失对象会导致不确定的行为。
您不应尝试通过忽略问题来使此工作正常进行,我的猜测是您正在VS中以调试模式运行该程序,因此它会捕获g ++无法捕获的错误,但是如果您通过调试器运行程序您可能会遇到相同的问题,尽管根据未定义行为的性质不能保证。
解决方法是修复代码,而不是忽略问题。
,请注意,您不能合法地修改const对象...
但是您可以在非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
)。