C++如何用引用进行转换工作

C++ how does cast with reference work?

本文关键字:转换 工作 引用 何用 C++      更新时间:2023-10-16

有人能解释一下下面代码中发生了什么吗?

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

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

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

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

对于第一种情况,直觉是:reinterpret_cast将左值引用视为指向其引用的类型的指针(并将上述转换应用于该指针(。

从形式上讲,标准上说:

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

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

和:

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

  1. 一元*运算符执行间接操作:应用它的表达式应该是指向对象类型的指针,或者是指向函数类型的指针并且结果是指向对象或函数的左值表达式所指向的。如果表达式的类型为"指向T的指针",则结果的类型为"T">

因此,在取消引用*cd之后,我们将获得类型为char的左值(与编写cd[0]时相同(。

5.2.10重新解释cast[expr.Reinterpret.cast]

  1. 如果类型为"pointer to T1"的表达式可以使用reinterpret_cast显式转换为类型为"pointer to T2",则类型为T1的glvalue表达式可以强制转换为类型"reference to T2"。结果引用的对象与源glvalue相同,但具有指定的类型。[注意:也就是说,对于lvalues,引用强制转换reinterpret_cast<T&>(x)与具有内置&*运算符的转换*reinterpret_cast<T*>(&x)具有相同的效果(对于reinterpret_cast<T&&>(x)也是如此(。--结束注释]不创建临时,不进行复制,也不调用构造函数(12.1(或转换函数(12.3(

这意味着,你有类似的东西

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

但也许比以上所有内容更重要的是:

3.10 Lvalue和右值[basic.lval]

如果程序试图通过不是以下类型之一的glvalue行为未定义:

  • 对象的动态类型
  • 对象的动态类型的cv限定版本
  • char或无符号char类型

也就是说,将"对char的引用"绑定到"unsigned short"类型的对象是可以的。但反之亦然(即,在您的示例中(是不可以的,因为访问这样的引用会调用未定义的行为。

带引用的强制转换与不带引用的同一强制转换有一点不同——不带引用强制转换会创建一个新的临时对象,而带引用强制执行会更改现有对象的类型。这在很多情况下都很重要,例如,在您的情况下,因为您将结果分配给了一个非常数引用。非常量引用不能用临时对象进行初始化。

顺便说一句,你知道你在这里所做的是违反了类型别名规则,这会产生未定义的行为吗?

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

类似于

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

unsigned short int & messageSize意味着messageSizeunsigned short int类型的变量,将存储该变量的内存区域应作为初始值设定项。

初始化器=reinterpret_cast<unsigned short int&>(*cd)说:取cd指向的位置的内存,并假装它包含一个unsigned short int

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

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

如果您的编译器没有执行别名优化,则可能会显示为,就好像您的代码目前"工作"一样。然而,代码被破坏了。