带有和没有引用的指针类型转换

iam*_*ind 5 c++ casting

由于A* pA;B* pB;,是否有任何以下类型的铸件(查询所有的C++风格的转换)之间的区别:

pB = reinterpret_cast<B*>(pA);      // pointer
pB = reinterpret_cast<B*&>(pA);     // pointer-reference
Run Code Online (Sandbox Code Playgroud)

Jam*_*nze 5

两者完全不同,至少在理论上(实际上可能在少数稀有机器上).第一个接受指向A的指针,并将其转换为指向B的指针; 从理论上讲,至少,这可能涉及规模和代表性的变化.(我实际上是在char*大于的机器上工作int*.我很怀疑任何这样的机器仍然存在,虽然可能在嵌入式世界......)第二个实际上相当于*reinterpret_cast<B**>(&pA); 它占用了位pA,并告诉编译器将它们解释为a B*.如果格式不同,运气不好,如果大小不同,您可能只访问部分内容pA或访问不属于的内存pA.

另外,第一个是右值,第二个是左值.因此,像:

++ reinterpret_cast<B*>( pA );
Run Code Online (Sandbox Code Playgroud)

是非法的,但是:

++ reinterpret_cast<B*&>( pA );
Run Code Online (Sandbox Code Playgroud)

不是.这是一种有用的技术,用于混淆代码,获取未对齐的指针,指向对象中间的指针,或其他不敢取消引用的指针.

一般来说,应该避免使用第二种形式,但很少有例外.Posix保证所有指针,包括指向函数的指针(但不是指向成员的指针-Posix指定的C ABI,它没有指向成员的指针),具有相同的大小和格式,因此第二种形式保证可以工作.并且它是您可以合法地将void*返回的dlsym转换为指向函数的指针的唯一方法:

int (*pf)( int );
reinterpret_cast<void*&>( pf ) = dlsym( handle, "functionName" );
Run Code Online (Sandbox Code Playgroud)

(在C中,你写道:

int (*pf)( int );
*(void**)( &pf ) = dlsym( handle, "functionName" );
Run Code Online (Sandbox Code Playgroud)

,请参阅 官方规范.)此类技巧允许指针类型之间的转换,否则不允许,但取决于标准中没有的额外保证.