以前不知道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*>是显而易见的。剩下的都是黑魔法。有人能分析一下这是如何实际工作的吗?
发布于 2013-04-24 22:54:45
首先,你有一个类型为_Tp&
reinterpret_cast‘
char&,以确保以后能够获取它的地址,而不用担心在原始类型中有一个过载的operator&;实际上它被强制转换为const volatile char&,因为reinterpret_cast总是可以合法地添加const和volatile限定符,即使它们不存在,但如果它们存在,它就不能删除它们(这确保了_Tp最初拥有的任何限定符,它们都不会干扰强制转换)。
const_cast'ed to char&,删除限定符(从法律上讲,现在!对于qualifiers).
const_cast可以做reinterpret_cast不能做的事情)返回(现在我们有一个简单的char*)
reinterpret_cast'ed reinterpret_cast & reinterpret_cast to _Tp* (包括原始const和volatile限定符,如果有)。编辑:由于我的回答已经被接受,我将彻底地补充说,选择char作为中间类型是由于对齐问题,以避免触发未定义的行为。查看@JamesKanze的评论(在问题下)以获得完整的解释。感谢James如此清晰地解释。
发布于 2013-04-24 22:56:02
简短版本:
不能为char重载operator&。因此,该类型被强制转换为char引用,以获取被保证为真实地址的内容。
由于对const_cast和reinterpret_cast的限制,这种转换是通过两次强制转换完成的。
更长的版本:
它正在执行三个连续的强制转换。
reinterpret_cast<const volatile char&>这实际上是转换为char&。const和volatile之所以存在,是因为_Tp可能是const或volatile,reinterpret_cast可以添加它们,但无法删除它们。
const_cast<char&>现在已经删除了const和volatile。const_cast可以做到这一点。
reinterpret_cast<_Tp*>(&result)现在,地址被获取,类型被转换回指向原始类型的指针。
发布于 2013-04-24 22:56:31
从里到外:
首先,它将__r类型强制转换为const volatile char&:,它强制转换为char&,因为它的类型肯定没有重载的operator&,这样做很时髦。const volatile之所以存在,是因为这些都是限制,可以用reinterpret_cast添加,但不能删除。_Tp可能已经是const和/或volatile,在这种情况下,在此类型转换中需要一个或两者。如果没有,演员们只是不必要地添加了它们,但它是为限制最严格的演员而写的。
const volatile,你需要一个const_cast,这将导致下一部分……const_cast<char&>。从那里,,
_Tp*。请注意,_Tp可能是const和/或volatile,这意味着可以在此时将这些内容添加回去。https://stackoverflow.com/questions/16195032
复制相似问题