简体   繁体   English

C ++如何使用引用进行转换?

[英]C++ how does cast with reference work?

Can anyone explain what's happening in the following code? 谁能解释下面的代码中发生了什么?

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

does it take the first 2 char of cd by reference and cast it to a 16 bit int? 是否通过引用将cd的前2个字符转换为16位int? when I remove the '&', the compiler complains about cannot cast from char to unsigned short int. 当我删除“&”时,编译器抱怨无法从char强制转换为unsigned short int。

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

The "intuitive" meaning of reinterpret_cast is "take a sequence of bits and treat it as if that sequence of bits has a different type". reinterpret_cast的“直观”含义是“采用位序列并将其视为该位序列具有不同的类型”。 That is not possible to do for types char and unsigned short , because they have different width. 对于charunsigned short类型,这是不可能的,因为它们的宽度不同。

As for the first case, the intuition is: reinterpret_cast treats lvalue reference as if it was a pointer to the type it refers (and applies mentioned conversion to that pointer). 对于第一种情况,直觉是: reinterpret_cast将左值引用当作是指向它引用的类型的指针一样对待(并将提及的转换应用于该指针)。

Formally, the standard says: 该标准正式表示:

4.2 Array-to-pointer conversion [conv.array] 4.2数组到指针的转换[conv.array]

  1. An lvalue or rvalue of type “array of NT” or “array of unknown bound of T” can be converted to a prvalue of type “pointer to T”. 可以将“ NT数组”或“ T的未知边界数组”类型的左值或右值转换为“指向T的指针”类型的prvalue。 The result is a pointer to the first element of the array. 结果是一个指向数组第一个元素的指针。

and: 和:

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

  1. The unary * operator performs indirection: the expression to which it is applied shall be a pointer to an object type, or a pointer to a function type and the result is an lvalue referring to the object or function to which the expression points. 一元*运算符执行间接操作:应用该表达式的表达式应为指向对象类型的指针或为函数类型的指针,并且结果为指向表达式所指向的对象或函数的左值。 If the type of the expression is “pointer to T”, the type of the result is “T”. 如果表达式的类型为“ T的指针”,则结果的类型为“ T”。

So, after dereferencing *cd we will get an lvalue of type char (same as if you wrote cd[0] ). 因此,在取消引用*cd我们将得到一个char类型的左值(就像您写了cd[0] )。

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

  1. A glvalue expression of type T1 can be cast to the type “reference to T2” if an expression of type “pointer to T1” can be explicitly converted to the type “pointer to T2” using a reinterpret_cast . 如果可以使用reinterpret_cast将类型“指向T1的指针”显式转换为类型“指向T2的指针”,则可以将类型T1的glvalue表达式强制转换为“对T2的引用”类型。 The result refers to the same object as the source glvalue, but with the specified type. 结果指向与源glvalue相同的对象,但是具有指定的类型。 [ Note: That is, for lvalues, a reference cast reinterpret_cast<T&>(x) has the same effect as the conversion *reinterpret_cast<T*>(&x) with the built-in & and * operators (and similarly for reinterpret_cast<T&&>(x) ). [注:即,对于左值,基准铸造reinterpret_cast<T&>(x)具有作为转换相同的效果*reinterpret_cast<T*>(&x)与内置&*运营商(以及类似地用于reinterpret_cast<T&&>(x) )。 — end note ] No temporary is created, no copy is made, and constructors (12.1) or conversion functions (12.3) are not called. —注释[end note]不会创建临时文件,不会创建副本,也不会调用构造函数(12.1)或转换函数(12.3)。

That means, you have got something like 那意味着,你有类似

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

But what is perhaps more important than all the above: 但是,可能比上述所有内容更重要的是:

3.10 Lvalues and rvalues [basic.lval] 3.10左值和右值[basic.lval]

If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined: 如果程序尝试通过以下类型之一以外的glvalue访问对象的存储值,则行为未定义:

  • the dynamic type of the object, 对象的动态类型,
  • a cv-qualified version of the dynamic type of the object, 对象动态类型的cv限定版本,
  • ... ...
  • a char or unsigned char type. 字符或无符号字符类型。

That is, binding a "reference to char" to an object of type "unsigned short" is ok. 也就是说,将“对char的引用”绑定到类型为“ unsigned short”的对象是可以的。 But doing vise-versa (ie, as in your example) is sort-of-not-ok, because accessing such reference would invoke undefined behavior. 但是反之亦然(例如,在您的示例中)是不可行的,因为访问此类引用将调用未定义的行为。

Cast with reference is different from the same cast without reference in one thing - cast without reference creates a new temporary object, while cast with reference changes the type of the already existing object. 具有引用的强制转换与没有引用的相同强制转换的不同之处在于,没有引用的强制转换会创建一个新的临时对象,而具有引用的强制转换会更改现有对象的类型。 This matters in many cases, for example, in your case, since you assigning a result to a non-const reference. 在许多情况下,例如在您的情况下,这很重要,因为您将结果分配给非常量引用。 Non-const references can not be inialized with temporary objects. 非const引用不能使用临时对象初始化。

On a side note, you know that what you are doing here is a violation on type aliasing rule, and is yields undefeined behaviour? 附带说明一下,您知道您在这里所做的事违反了类型别名规则,并且会产生不合法的行为吗?

unsigned short int & messageSize means that messageSize is a variable of type unsigned short int , and the memory area where that variable will be stored shall be given as initializer. unsigned short int & messageSize表示messageSizeunsigned short int类型的变量,并且将存储该变量的存储区应作为初始化程序。

The initializer =reinterpret_cast<unsigned short int&>(*cd) says: take the memory at the location being pointed to by cd , and pretend it contains a unsigned short int . 初始化程序=reinterpret_cast<unsigned short int&>(*cd)说:在cd指向的位置获取内存,并假装它包含unsigned short int

The result is that if you try to read and write messageSize , then you will try to read and write a unsigned short int in a memory location that contains something else. 结果是,如果您尝试读写messageSize ,那么您将尝试在包含其他内容的内存位置中读写一个unsigned short int This causes undefined behaviour. 这会导致不确定的行为。

There are a few situations in which it is OK to pretend a memory location contains an object that it actually doesn't; 在某些情况下,可以假装内存位置包含实际上不包含的对象; this is not one of them. 这不是其中的一个。

If your compiler is not performing aliasing optimizations then it might appear as if your code "works" for now. 如果您的编译器没有执行别名优化,那么它看起来好像您的代码现在“可以正常工作”。 However the code is broken. 但是,代码已损坏。

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

类似于

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM