C ++如何使用引用工作?

时间:2015-08-28 20:56:13

标签: c++ casting char

有人可以解释以下代码中发生了什么吗?

char cd[1024];
unsigned short int & messageSize =reinterpret_cast<unsigned short int&>(*cd);

是否通过引用获取cd的前2个字符并将其转换为16位int? 当我删除'&amp;'时,编译器抱怨无法从char转换为unsigned short int。

unsigned short int messageSize =reinterpret_cast<unsigned short int>(*cd);

4 个答案:

答案 0 :(得分:3)

&#34;直观&#34; reinterpret_cast的含义是&#34;取一个位序列并将其视为该位序列具有不同的类型&#34;。对于charunsigned short类型,这是不可能的,因为它们的宽度不同。

至于第一种情况,直觉是:reinterpret_cast将左值引用视为指向它引用的类型的指针(并将所提到的转换应用于该指针)。

正式地,标准说:

  

4.2数组到指针的转换[conv.array]

     
      
  1. 类型为“N T数组”或“未知T的数组”的左值或右值可以转换为“指向T的指针”类型的prvalue。结果是指向数组第一个元素的指针。
  2.   

  

5.3.1一元运算符[expr.unary.op]

     
      
  1. 一元*运算符执行间接:应用它的表达式应该是指向对象类型的指针,或指向函数类型的指针,结果是引用对象或函数的左值   表达点所指向的。如果表达式的类型是“指向T的指针”,则结果的类型为   “T”。
  2.   

因此,在解除引用*cd之后,我们会得到一个char类型的左值(就像你写cd[0]一样)。

  

5.2.10重新解释演员[expr.reinterpret.cast]

     
      
  1. 如果使用reinterpret_cast可以将“指向T1的指针”类型的表达式显式转换为“指向T2的指针”类型,则可以将类型T1的glvalue表达式强制转换为“对T2的引用”类型。结果引用与源glvalue相同的对象,但具有指定的类型。 [注意:也就是说,对于左值,参考广告reinterpret_cast<T&>(x)与内置*reinterpret_cast<T*>(&x)&运算符的转化*具有相同的效果(同样适用于reinterpret_cast<T&&>(x))。 - 尾注]没有创建临时,没有复制,也没有调用构造函数(12.1)或转换函数(12.3)。
  2.   

这意味着,你有类似

的东西
*reinterpret_cast<unsigned short *>(&cd[0])

但是,或许比以上所有更重要的是:

  

3.10 Lvalues和rvalues [basic.lval]

     

如果程序试图通过访问对象的存储值   行为是除以下类型之一以外的glvalue   未定义:

     
      
  • 对象的动态类型,
  •   
  • 对象的动态类型的cv限定版本,
  •   
  • ...
  •   
  • char或unsigned char类型。
  •   

即绑定&#34;引用char&#34;对于#&#34; unsigned short&#34;没关系。但是反之亦然(例如,在你的例子中)并不好,因为访问这样的引用会调用未定义的行为。

答案 1 :(得分:1)

使用引用进行强制转换不同于没有引用的同一强制转换 - 没有引用的强制转换会创建一个新的临时对象,而使用引用进行强制转换会更改已存在对象的类型。这在很多情况下很重要,例如,在您的情况下,因为您将结果分配给非const引用。非const引用不能用临时对象进行初始化。

在旁注中,您知道您在此处所做的是违反类型别名规则,并且会产生不确定的行为吗?

答案 2 :(得分:1)

unsigned short int & messageSize表示messageSizeunsigned short int类型的变量,存储该变量的内存区域应作为初始值。

初始值设定项=reinterpret_cast<unsigned short int&>(*cd)说:在cd指向的位置取内存,并假装它包含unsigned short int

结果是,如果您尝试读写messageSize,那么您将尝试在包含其他内容的内存位置中读取和写入unsigned short int。这会导致未定义的行为。

在某些情况下可以假装内存位置包含实际上没有的对象;这不是其中的一个。

如果您的编译器没有执行别名优化,那么可能会出现,就好像您的代码现在“正常”一样。但是代码被破坏了。

答案 3 :(得分:0)

reinterpret_cast<unsigned short int&>(*cd);

类似于

*reinterpret_cast<unsigned short int*>(cd);