C++中,从指向常量的指针到指向非常量的指针的强制转换是否无效?

8

我相信以下代码不应该编译通过,但是在g++中却可以编译通过!您可以在http://codepad.org/MR7Dsvlz上看到它的编译结果。

代码如下:

#include <iostream>

using namespace std;

int main() {
    int x = 32 ;
    // note: if x is, instead, a const int, the code still compiles, 
    // but the output is "32".

    const int * ptr1 = & x ;

    *((int *)ptr1) = 64 ; // questionable cast
    cout << x ;           // result: "64"
}

编译这个代码时,g++是否存在错误?


如果你想消除const限定(并且确定是允许的),惯用的C++方法是使用 const_cast<int*>(ptr1) - 虽然C语言风格的转换也可以,正如你刚才所看到的。 - Michael Anderson
1
这篇文章很有帮助:https://dev59.com/MHRC5IYBdhLWcg3wROtQ - Pubby
3个回答

10

不行。根据C++标准§5.4.4的规定,C风格转换可以执行的强制类型转换包括:

— a const_cast (5.2.11),
— a static_cast (5.2.9),
— a static_cast followed by a const_cast,
— a reinterpret_cast (5.2.10), or
— a reinterpret_cast followed by a const_cast

这被广泛称为“去除const”,如果编译器无法编译该代码,则不符合标准的那部分。

正如ildjarn指出的那样,通过去除const修改const对象是未定义行为。此程序不会展示未定义行为,因为虽然指针指向的对象是const类型,但该对象本身不是const(感谢R.Martinho和eharvest纠正我的错误阅读)。


3
你提出了自相矛盾的问题。如果回答标题问题是“是”,则回答正文问题就是“不是”。下次请更加小心。 - Rob Kennedy
为什么你说它是未定义行为?cout << x ; // result: "64" 无论使用哪个编译器和C++标准,64都是正确的结果。 - Hicham
@eharvest 修改const对象是未定义的行为。仅仅因为你通过指向非const的指针对其进行解引用并不会使对象变成非const - Seth Carnegie
我已经做了很多次这种类型的转换(const_cast)。你有没有一个例子,在使用const_cast修改常量对象的内容后不起作用? - Hicham
1
但是*被修改的对象不是const*。被修改的对象是int x = 32; - R. Martinho Fernandes
显示剩余6条评论

3

不,g++没有编译您的代码出错。您所做的转换是有效的。

(int *)ptr1 是C语言的转换方式。在C++中,等效的方式是 const_cast<int*>(ptr1)。第二种方式更易于阅读。

但是,需要进行此转换(以修改常量变量)显示了设计上的问题。


1

代码行 *((int *)ptr1) = 64 等同于 *(const_cast<int*>(ptr1)) = 64。在使用强制类型转换符时,const_cast 是首先执行的转换。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接