伪代码:
template <class _T>
const _T & as_const( _T & _t){
return _t;
}
他不会创建新的对象, 也不会修改原对象;
vector< int> arr = {1, 2, 3};
for( int & i : std::as_const( arr)) ' 错 '
_Tp * addressof(_Tp& __r){ return std::__addressof(__r);}
const _Tp * addressof( const _Tp &&) = delete; ' 不允许对右值的取地址 '
其实就是 &
取地址, 封装成函数, 比较好;
代码长了, 一个&
号, 很容易看不见 或忽略… 这样封装性比较好;
T & ref = obj;
这里的引用符号&
, 和上面取地址时的问题一样, 一个符号 很容易看不见或丢失… 封装成函数/类, 更符号高级语言的风格.
class reference_wrapper{
_Tp * _M_data;
public:
reference_wrapper( _Tp & _d)
: _M_data( std::__addressof( _d)){}
reference_wrapper(_Tp&&) = delete; ' 不允许对右值的引用 '
operator _Tp&(){ return this->get();} ' 可以强转为: _Tp & 引用 '
_Tp & get(){ return *_M_data;}
};
顾名思义, 他是对T &
这个引用, 做了一层封装;
reference_wrapper<_Tp> ref(_Tp& __t){ return reference_wrapper<_Tp>(__t); }
reference_wrapper< const _Tp> ref( const _Tp& __t){ return reference_wrapper< const _Tp>(__t); }
void ref(const _Tp&&) = delete;
void cref(const _Tp&&) = delete; ' 不允许对右值的引用 '
ref 和 cref
, 就类似于一个宏, 他的本质 就是构造一个reference_wrapper
对象;
void func( const T & _t){}
T t;
reference_wrapper< T> ref = t;
func( ref); ' ref会强转为 T&类型; '
func( ref.get());
func( std::ref( t));
func( std::cref( t)); ' 一般这2种用的比较多 '
这样, 你使用std::ref( t) 或 cref( t)
, 你一看就可以看出, 这传递的是引用/const引用;
当然, reference_wrapper
的作用 不仅于此, 他的功能 暂时还了解不全
比如, 线程函数的参数, 比如是引用参数; 你传递( obj)
他其实不是引用传递, 而是会copy一份副本!!! 并不是引用
而 std::ref( obj)
, 他是真正的引用传递