STL实现细节之addressof()的实现

来源:互联网 发布:单片机圆孔插座 编辑:程序博客网 时间:2024/06/08 18:46

在C++11中,addressof(T& r)函数用于获得指向某个对象的地址(更早的STL通常也会实现该函数),也就是返回它的指针。通常来说,只要使用取址符&即可完成,为什么还要大费周章去设计这么个函数?

C++11的标准文档中对addressof(T& r)函数的说明是这样的:

Returns: The actual address of the object or function referenced by r, even in the presence of an overloaded operator&.

考虑下面代码:

class test{public:    test* operator&()    {        return NULL;    }};int main(){    test t;    test *p = &t1;    return 0;}

对test对象使用取址符&是无法达到预期效果的。

再看看GCC中(位于bits/move.h中)该方法的实现:

template<typename _Tp>    inline _Tp*__addressof(_Tp& r)     {      return reinterpret_cast<_Tp*>    (&const_cast<char&>(reinterpret_cast<const volatile char&>(r)));    }

粗看代码,我们可以大概明白问题的解决思路。首先将传入的引用转化为char类型的引用,然后使用&取址,避开了操作符重载的影响。

不过里面的一些细节还是需要注意的:

该函数首先把传入的引用转化为const volatile char 类型的引用。
其中,const关键字在这里的作用是,保证类型转换成功。
注意到,这是一个模板函数,传入的引用有可能具有const属性,即const T&,此时如果使用reinterpret_cast把它转换为char&,就属于非法转换,编译器会报错。volatile同理。因而需要采用先把引用加上const volatile属性然后再使用const_cast将其去除这种看似走弯路的做法。

针对这种情况还有一种解决方案,就是利用函数的重载。即下面这种写法:

//普通版本template<typename _Tp>    inline _Tp*__addressof(_Tp& r)     {      return reinterpret_cast<_Tp*>          (&reinterpret_cast<char&>(r));    }//const版本template<typename  _Tp>    inline const _Tp*__addressof(const _Tp& r) {    return reinterpret_cast<const _Tp*>        (&reinterpret_cast<const char&>(r));}...

但这样一来就需要为它编写四个(普通,const, volatile, const volatile)重载函数,未免显得太过笨拙。

0 0