指针类型转换的引用和非引用方式

5

假设 A* pA;B* pB;,下面这些类型转换(查询所有C++风格的转换)有任何区别吗:

pB = reinterpret_cast<B*>(pA);      // pointer
pB = reinterpret_cast<B*&>(pA);     // pointer-reference
4个回答

5
这两者在理论上(可能在少数机器上也是如此)有很大的区别。第一种方法需要一个指向A的指针,并将其转换为B的指针;至少在理论上,这可能涉及大小和表示形式的改变。(我曾经在一些机器上工作过,其中char*比int*还要大,虽然可能在嵌入式领域仍存在这样的机器...)第二种方法实际上等同于*reinterpret_cast(&pA);它获取pA中的位,并告诉编译器将它们解释为B*。如果格式不同,那就太糟糕了,如果大小不同,你可能只能访问pA的一部分或访问不属于pA的内存。
另外,第一种方法是rvalue,第二种方法是lvalue。因此,像以下这样的东西:
++ reinterpret_cast<B*>( pA );

虽然是非法的,但是:

++ reinterpret_cast<B*&>( pA );

这是一种有用的代码混淆技术,可以获得未对齐指针、指向对象中间或其他不敢解引用的指针。

通常情况下,应避免使用第二种形式,但有时会有例外。Posix保证所有指针(包括指向函数的指针,但不包括指向成员的指针-Posix指定了C ABI,它没有指向成员的指针)具有相同的大小和格式,因此第二种形式是保证可行的。而且这是唯一的合法方式将dlsym返回的void*转换为指向函数的指针:

int (*pf)( int );
reinterpret_cast<void*&>( pf ) = dlsym( handle, "functionName" );

(在 C 中,您会这样写:)
int (*pf)( int );
*(void**)( &pf ) = dlsym( handle, "functionName" );

这些技巧允许在标准不允许的指针类型之间进行转换,但这取决于额外的保证,详情请参见官方规范

1

reinterpret_cast 是实现定义的。理论上结果可能不同,但在实践中,您可以假设结果将是相同的,因为 typeid(B*) 等于 typeid(B*&) => 实际上在两种情况下都转换为相同的类型。


0

没有任何功能上的区别。

如果你使用后一种变体,显然会有可维护性的差异。你的同事可能会认为你吸了什么东西。 ;-)


0

没有任何区别。

pB = reinterpret_cast<B*>(pA);      // pointer 

将类型转换为指针B*

pB = reinterpret_cast<B*&>(pA);     // pointer-reference

将引用强制转换为指针。

注意:不存在指向引用的指针。


2
在他的问题中,OP已经提到第一个是指针,第二个是指向指针的引用。 - Mihran Hovsepyan
@Mihran Hovsepyan:OP说“Pointer-Reference”,这种东西不存在吧?只能有指针的引用。 - Alok Save
2
在编程中,“指针引用”与“指针的引用”是相同的,而不是“引用的指针”。 - Mihran Hovsepyan
@Mihran Hovsepyan:英文很好。 - Alok Save

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接