1. 程式人生 > >C++11--右值引用(Perfect Forwarding)

C++11--右值引用(Perfect Forwarding)

/* 
 * 右值引用 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. 完美傳遞
 */