【发布时间】:2017-10-24 18:48:37
【问题描述】:
以前不知道std::addressof 的存在,它存在的原因对我来说是有意义的:作为在存在重载operator& 的情况下获取地址的一种方式。然而,实现稍微不透明。来自gcc 4.7.1:
template<typename _Tp>
inline _Tp*
__addressof(_Tp& __r) _GLIBCXX_NOEXCEPT
{
return reinterpret_cast<_Tp*>
(&const_cast<char&>(reinterpret_cast<const volatile char&>(__r)));
}
reinterpret_cast<_Tp*> 很明显。剩下的就是黑魔法了。有人可以分解这实际上是如何工作的吗?
【问题讨论】:
-
强制转换为
char&(或char *)可以避免破坏严格的别名规则,并且operator&不能为char等内置类型重载。所以你最终得到了一个指向_Tp基地址的指针。 -
@Praetorian 别名规则在这里不是问题,因为您不会取消引用结果。之所以使用
char,是因为它不能有对齐要求;如果你使用int,并且int的对齐比_Tp更严格,转换可能会改变实际地址。 -
@JamesKanze Ahh,当然,没有考虑过不阅读演员表的结果。幸好我发表了评论而不是答案:)
-
@syam 使用转换结果(除非它是字符类型)是未定义的行为,因此实现可以做任何它想做的事情。在字节寻址的机器上,
reinterpret_cast转换通常在机器代码级别不执行任何操作。然而,在 word 寻址的机器上,int*通常会小于char*;char*到int*的转换会丢失数据。 -
@syam re "anything it want": 有一个要求,如果一个地址被转换成一个没有更严格对齐要求的类型,然后再回到原来的类型,结果指针将与原始指针进行比较。但就标准要求而言,就是这样。