使用 const_cast 抛弃常量
casting away the constness using const_cast
没有。这个问题不重复
When should static_cast, dynamic_cast, const_cast and reinterpret_cast be used?
此处提出的问题与 link 描述为重复的问题完全不同。
第一个问题:
我在下面的两种情况下使用 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.
第一个答案:在你的例子中,你试图强制编译器做一些可以像这样解释的事情
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_cast
const 值,因为它会导致未定义的行为。您只能从指针或引用中删除常量,这些指针或引用最终指向的不是真正的东西const
,只有指针不允许您修改它的值。
这个问题在 this 回答中有很好的描述。
const_cast
应用于表达式,而不是对象,它本身也是一个表达式:
§ 5.2.11 [expr.const.cast]/p1:
The result of the expression const_cast<T>(v)
is of type T
. If T
is an lvalue reference to object type, the
result is an lvalue; if T
is an rvalue reference to object type, the result is an xvalue; otherwise, the result
is a prvalue and the lvalue-to-rvalue (4.1), array-to-pointer (4.2), and function-to-pointer (4.3) standard
conversions are performed on the expression v
const_cast<int*>(i)=m;
此调用无效,因为赋值的左侧有一个 prvalue 值类别,而 int*
prvalue 不支持赋值。正确的语法是 const_cast<int*&>(i)=m;
,但由于在您的示例中声明了 i
const
,它将调用未定义的行为 †.
const_cast<int*>(*i1)=l;
取消引用 int*
类型的指针会创建一个左值值类别的表达式,并且因为强制转换表达式在赋值的左侧,所以它应该是一个左值引用类型的强制转换,即 const_cast<int&>(*i1)=10;
(前提是 i1
指向的任何内容都未声明 [=20=])。
const_cast<int>(a)=b;
const_cast<int>(a)
部分本身是有效的,特别是您可以将 const_cast 应用于表示既不是指针类型也不是引用类型的对象的表达式。但由于它位于分配的左侧,因此无法编译。即使您将其更改为 const_cast<int&>(a)=b;
,它也会触发未定义的行为,因为 a
被声明为 const
†.
† § 7.1.6.1 [dcl.type.cv]/p4:
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.
没有。这个问题不重复 When should static_cast, dynamic_cast, const_cast and reinterpret_cast be used?
此处提出的问题与 link 描述为重复的问题完全不同。
第一个问题: 我在下面的两种情况下使用 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.
第一个答案:在你的例子中,你试图强制编译器做一些可以像这样解释的事情
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_cast
const 值,因为它会导致未定义的行为。您只能从指针或引用中删除常量,这些指针或引用最终指向的不是真正的东西const
,只有指针不允许您修改它的值。
这个问题在 this 回答中有很好的描述。
const_cast
应用于表达式,而不是对象,它本身也是一个表达式:
§ 5.2.11 [expr.const.cast]/p1:
The result of the expression
const_cast<T>(v)
is of typeT
. IfT
is an lvalue reference to object type, the result is an lvalue; ifT
is an rvalue reference to object type, the result is an xvalue; otherwise, the result is a prvalue and the lvalue-to-rvalue (4.1), array-to-pointer (4.2), and function-to-pointer (4.3) standard conversions are performed on the expressionv
const_cast<int*>(i)=m;
此调用无效,因为赋值的左侧有一个 prvalue 值类别,而 int*
prvalue 不支持赋值。正确的语法是 const_cast<int*&>(i)=m;
,但由于在您的示例中声明了 i
const
,它将调用未定义的行为 †.
const_cast<int*>(*i1)=l;
取消引用 int*
类型的指针会创建一个左值值类别的表达式,并且因为强制转换表达式在赋值的左侧,所以它应该是一个左值引用类型的强制转换,即 const_cast<int&>(*i1)=10;
(前提是 i1
指向的任何内容都未声明 [=20=])。
const_cast<int>(a)=b;
const_cast<int>(a)
部分本身是有效的,特别是您可以将 const_cast 应用于表示既不是指针类型也不是引用类型的对象的表达式。但由于它位于分配的左侧,因此无法编译。即使您将其更改为 const_cast<int&>(a)=b;
,它也会触发未定义的行为,因为 a
被声明为 const
†.
† § 7.1.6.1 [dcl.type.cv]/p4:
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.