2

不。这个问题在不重复 什么时候应该使用 static_cast、dynamic_cast、const_cast 和 reinterpret_cast?

这里提出的问题与描述为重复的链接没有任何相似之处。

第一个问题: 我在以下两种情况下使用 const_cast。其中之一有效。另一个没有。

1. int* const //有效。

在这种语法中,变量指向的地址不能更改。所以我使用 const_cast 如下,它可以工作:

`
int j=3;
int *k=&j;
int *m=&j;
int* const i=k; 
const_cast<int*>(i)=m; //OK: since i=m would not work so cast is necessary`

2. const int* //不起作用。

指向的地址可以更改,但值不能更改(尽管可以通过使变量指向不同的地址来更改)。我使用的 const_cast 似乎在这里不起作用:

`
int j=9;
int *k=&j;
const int* i1=0;
i1=k; //OK
//*i1=10;//ERROR.`

所以我尝试通过各种方式进行如下类型转换,但没有任何效果:

const_cast<int*>(i1)=10;
const_cast<int*>(*i1)=l;
*i1=const_cast<int>(l);
*i1=const_cast<int*>(10);

第二个问题: 所有类型转换是否仅可用于指针和引用?以下示例在图片中没有指针或引用的情况下是否无效?

const int a=9;
int b=4;
const_cast<int>(a)=b; //cannot convert from 'int' to 'int'. why is compiler
                      //trying to convert from int to int anyways or fails         
                      //when both the types are same.
4

2 回答 2

3

const_cast应用于表达式,而不是对象,它本身也是一个表达式

§ 5.2.11 [expr.const.cast]/p1:

表达式的结果const_cast<T>(v)是类型T。如果T是对对象类型的左值引用,则结果是左值;如果T是对对象类型的右值引用,则结果是一个 xvalue;否则,结果为纯右值,并且对表达式执行左值到右值 (4.1)、数组到指针 (4.2) 和函数到指针 (4.3) 标准转换v

  1. const_cast<int*>(i)=m;

此调用无效,因为赋值的左侧有一个纯右值值类别,而int*纯右值不支持赋值。正确的语法是const_cast<int*&>(i)=m;,但由于i在您的示例中已声明const,它将调用未定义的行为†</sup>。

  1. const_cast<int*>(*i1)=l;

取消引用类型的指针int*会创建一个左值值类别的表达式,并且由于强制转换表达式在赋值的左侧,它应该是一个左值引用类型的强制转换,即const_cast<int&>(*i1)=10;(假设任何i1指向的都没有声明const)。

  1. const_cast<int>(a)=b;

const_cast<int>(a)部分本身是有效的,特别是您可以将 const_cast 应用于表示对象的表达式,该对象既不是指针类型也不是引用类型。但由于它位于分配的左侧,因此无法编译。即使您将其更改为const_cast<int&>(a)=b;它也会触发未定义的行为,因为a已声明const †</sup>。


†</sup> § 7.1.6.1 [dcl.type.cv]/p4:

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

于 2015-08-18T12:01:18.247 回答
2

第一个答案:在你的例子中,你试图强制编译器做一些可以这样解释的事情

const_cast<int*>(i1)=10; //int* = int: assign address to pointer
const_cast<int*>(*i1)=l; //const_cast<int*>(int): cast the value under pointer to pointer
*i1=const_cast<int>(l); //const_casting from const values is forbidden
*i1=const_cast<int*>(10); //10 is an rvalue

您在这里真正想要做的是取消引用一个非常量的指针。这就是为什么你需要这样做:

int j = 9;
int *k = &j;
const int* i1 = 0;
i1 = k;
*(const_cast<int*>(i1)) = 10;

这相当于

int j = 9;
int *k = &j;
const int* i1 = 0;
i1 = k;
int* temp = const_cast<int*>(i1); //you get rid of 'const'...
*temp = 10; //...and now you assign value as you wanted to - this operation became available

第二个答案:禁止const_castconst 值,因为它会导致未定义的行为。您只能从指向const最终不是真的东西的指针或引用中删除常量,并且只有指针不允许您修改其值。

这个问题在这个答案中得到了很好的描述。

于 2015-08-18T11:46:43.513 回答