猫猫哥

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
/* 
 * 右值引用 2: Perfect Forwarding
 */


void foo( boVector arg );
// boVector既有移动构造又有拷贝构造

template< typename T >
void relay(T arg ) {
   foo(arg);  
}

int main() {
   boVector reusable = createBoVector();
   relay(reusable);
   ...
   relay(createBoVector());
}


// 什么才能叫完美传递,Perfect Forwarding
/*
 * 1. 没有昂贵且不必要的拷贝构造
 * 2. 右值传递为右值,左值传递为左值
 */



// 解决方法:
template< typename T >
void relay(T&& arg ) {
  foo( std::forward<T>( arg ) );
}

//* 注意:之所有有效是因为,类型T是模板类型
    


/* 
 * 引用折叠的规则 ( C++ 11 ):
 * 1.  T& &   ==>  T&
 * 2.  T& &&  ==>  T&
 * 3.  T&& &  ==>  T&
 * 4.  T&& && ==>  T&&  //只有两个右值引用还是右值引用
 */




template< classs T >
struct remove_reference;    // 移除类型T的引用

// T为int&
remove_refence<int&>::type i;  // int i;

// T为int
remove_refence<int>::type i;   // int i;



template< typename T >
void relay(T&& arg ) {
   ...
}

/*
 * 右值引用由type&&指定
 *
 * 那么type&&表示右值引用?
 */


// T&&变量以右值 => 右值引用
  relay(9); =>  T = int&& =>  T&& = int&& && = int&&

// T&&变量以左值初始化 => 左值引用
  relay(x); =>  T = int&  =>  T&& = int& && = int&

// T&&是一个通用引用: 左值,右值,const,non-const等
// 前提条件:
// 1. T是一个模板类型
// 2. T发生了类型折叠
//    - T 是函数模板类型,不是类模板了类型



template< typename T >
void relay(T&& arg ) {
  foo( std::forward<T>( arg ) );    //    将arg转回T&&类型
}

// std::forward()的实现
template<class T>
T&& forward(typename remove_reference<T>::type& arg) {  
  return static_cast<T&&>(arg);
} 



// std::move()和std::forward()比较
std::move<T>(arg);    // 将arg变成一个右值类
std::forward<T>(arg); // 将arg变成T&&类型



/*
 * 总结:
 *
 * 右值引用两个主要使用地方:
 * 1. 移动语义
 * 2. 完美传递
 */
posted on 2018-12-30 13:40  猫猫哥  阅读(397)  评论(0编辑  收藏  举报