C++:类型转换——static_cast和const_cast

型转换是我们经常遇到的问题,C-type的类型转换都很熟悉也很简单,但是C-type的显式类型转换几乎任何类型之间都可以转换,显得太”流氓”,很难判断是否正确,是否安全。因此C++引入了四种全新的类型转换机制,static_cast、const_cast、reinterpret_cast、dynamic_cast,后两种过于复杂,了解的不好,待以后再做探讨。

static_cast

任何具有明确定义的类型转换,只要不包含底层const(见最下注释),都可以使用static_cast.

基本语法如下:

1 typename value = static_cast<typename>(expression);
1 double x = static_cast<double> (y);//y可以是多种类型

The result of static_cast(expression) belongs to one of the following value categories:

If typename is an lvalue reference type or an rvalue reference to a function type, static_cast(expression) is an lvalue.
If typename is an rvalue reference to an object type, static_cast(expression) is an xvalue.
In all other cases, static_cast(expression) is a (prvalue)rvalue.
实际上,将大型算术类型转换给小型算术类型时很有用(如double转换为int),使用static_cast告诉编译器,我知道会损失精度但是并不在乎,这样编译器就不会发出警告。

更让人高兴的是,static_cast对于编译器无法自动执行的类型转换提供了很好的支持。

例如:

1 double somevalue = 3.14;
2 void *p = &somevalue;//正确:任何非const对象的地址都能存入void*,但是不能通过p修改somevalue
3 double *pd = static_cast<double*>(p);//正确

经过测试,*p和*pd都是指向somevalue的。

const_cast

const_cast只能改变运算对象的底层const.
语法规则如下:

1 type something = const_cast<type>(expression);
2 const char* pc;
3 char *p = const_cast<char*>(pc);

要注意的是,这种转换只能更改引用或者指针,也就是说下面这种写法是报错的。

1 const int a = 100;
2 int b = const_cast<int>(a);//error: invalid use of const_cast with type 'int', which is not a pointer, reference, nor a pointer-to-data-member type

对于将常量对象转换成非常量对象的行为,我们称其为“去掉const性质”(cast away the const),一旦失去了某个对象的const性质,编译器将不再阻止我们对该对象进行修改但是一定要注意的是:如果对象本身是一个常量,将常量转换为非常量后,使用转换后的非常量修改值是未定义行为(undefined behavior),虽然编译器不会报错也不会waring,但是不同的编译器对这种行为有不同的判断,因此这是一种非常危险的行为。但如果对象本身不是一个常量,在cast away the const 后,修改其内容是合法的。

以下摘自IBM Knowledge Center:

#include <iostream>
using namespace std;

void f(int* p) {
  cout << *p << endl;
}

int main(void) {
  const int a = 10;
  const int* b = &a;

  // Function f() expects int*, not const int*
  //   f(b);
  int* c = const_cast<int*>(b);
  f(c);

  // Lvalue is const
  //  *b = 20;

  // Undefined behavior
  //  *c = 30;

  int a1 = 40;
  const int* b1 = &a1;
  int* c1 = const_cast<int*>(b1);//a1 is not a const,so we can use c1 to change the value of al

  // Integer a1, the object referred to by c1, has
  // not been declared const
  *c1 = 50;

  return 0;
}

以下是官方解释:

The compiler does not allow the function call f(b). Function f() expects a pointer to an int, not a const int.//编译器不允许调用f(b)因为f()的参数为int*不是const int*,此时用const_cast可以去掉const后传递进去
Consequently the compiler does allow the function call f(c).//c是转换类型得到的,可以调用f(int*)
The compiler would not allow the assignment *b = 20 because b points to an object of type const int. The compiler does allow the *c = 30, but the behavior of this statement is undefined //不允许*b = 20,这是const_cast规定的,但是实际上不会报错,这是一种未定义行为,不同的编译器有不同的处理结果
However, if you cast away the constness of an object that has not been explicitly declared as const, you can modify it safely. In the above example, the object //不过如果原对象本身是非const的,通过c1修改a1是完全安全的
———————————————————————————————————————————————————————————————————————————————

PS:底层const和顶层const的定义如下:

As we’ve seen, a pointer is an object that can point to a different object. As a result,we can talk independently about whether a pointer is const and whether the objectsto which it can point are const. We use the term top-level const to indicate that thepointer itself is a const. When a pointer can point to a const object, we refer to that const as a low-level const。

指针本身是const,使用术语顶层const。
指针指向的对象是const,使用术语底层const。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值