1. 程式人生 > >C++11新特性(66)- 用static_cast將左值轉換為右值

C++11新特性(66)- 用static_cast將左值轉換為右值

溫故而知新

本文涉及兩個概念,static_cast和右值引用,在閱讀本文之前,最好先閱讀下面的文章。

使用std::move

考察下面兩個函式:

除了引數型別一個是左值引用,一個是右值引用以外都一樣。結合前面的文章可以得出下面的結論:左值引用表明這個值可能被修改,右值引用就是對外要求接管引數資料的權利。相應的的,右值引用的情況下就會要求呼叫者明確表明放棄權利。

這裡放棄權利的方式就是通過std::move函式,就像上圖中fr函式中做的那樣。

理解std::move

下面是std::move的原始碼:

先看函式體,只做了一件事:使用static_cast將實參t顯式轉換為另外一種型別,這個型別為:

typename用來指示後面的表示式是一個型別而不是變數,先將其忽略;接下來去掉否面的&&(暫時不考慮),程式碼變成下面這個樣子:

我們知道(不知道也會讓你知道),remove_reference的功能是去掉引用型別修飾符。

例如: 如果T的型別為int&或者int&& 則返回int; 如果T的型別為int也返回int;

再考慮剛才忽略的&&修飾符,可以得到以下結論:static_cast的目標型別為輸入型別T去掉可能存在的引用修飾,然後加上右值引用修飾。

也就是說,std::move的功能是使用static_cast將T,T&,T&&全都顯式轉換為T&&。

作者見解

右值引用的作用是要求資料提供者放棄資料的所有權,而std::move就是放棄資料所有權的手段。雙方可以在編譯層次解決。

覺得本文有幫助?請分享給更多人。

閱讀更多更新文章,請掃描下面二維碼,關注微信公眾號【面向物件思考】

相關推薦

C++11特性66- static_cast轉換

溫故而知新 本文涉及兩個概念,static_cast和右值引用,在閱讀本文之前,最好先閱讀下面的文章。 使用std::move 考察下面兩個函式: 除了引數型別一個是左值引用,一個是右值引用以外都一樣。結合前面的文章可以得出下面的結論:左值引用表明這個

C++11特性

auto關鍵字 C語言中其實就有auto關鍵字,修飾可變化的量,但是由於平時我們直接使用int a = 10;也是宣告變數,編譯器已經自動幫我們加上了auto關鍵字,是C語言中應用最廣泛的一種型別,也就是說,省去型別說明符auto的都是自動變數! 隨著時代進步,

C++11特性1-long long

溫故而知新迄今為止的職業生涯中,有過兩次集中時間學習C++的經歷。第一次大概是在1994年前後,那時非計算機專業大學畢業剛接觸C++,學的是還是BorlandC++3.1的手冊。許多東西都是一知半解就開始了應用,但即使是這樣,還是充分感覺到C++的強大,非常喜歡C++帶來的那

C++11特性2- 列表初始化

以前什麼樣C或者C++在初始化陣列時,可以使用下面的花括號加初始值的形式:intint_array[]={1,2,3,4,5};在C++中,如果有下面這樣一個類:classTester{public:Tester(intvalue):m_value(value*2){}voi

C++11特性51- 移動建構函式通常應該是noexcept

不會丟擲異常的移動建構函式 拷貝建構函式通常伴隨著記憶體分配操作,因此很可能會丟擲異常;移動建構函式一般是移動記憶體的所有權,所以一般不會丟擲異常。 C++11中新引入了一個noexcept關鍵字,用來向程式設計師,編譯器來表明這種情況。 noexc

C++11特性11- 標準庫函式begin和end

遍歷陣列元素的方法假設有一個數組:inta1[]{1,2,3,4,5};遍歷陣列的所有元素,可以這樣:for(unsignedinti=0;i<sizeof(a1)/sizeof(a1[0]);++i){cout<<a1[i]<<endl;}也可

C++11特性之 std::forward(完美轉發)

tails array sin .com std utili res details calling 我們也要時刻清醒,有時候右值會轉為左值,左值會轉為右值。 (也許“轉換”二字用的不是很準確) 如果我們要避免這種轉換呢? 我們需要一種方法能按照參數原來的類型轉發到另一個函

C++11 帶來的特性 2—— 統一初始化Uniform Initialization

1 統一初始化(Uniform Initialization) 在C++ 11之前,所有物件的初始化方式是不同的,經常讓寫程式碼的我們感到困惑。C++ 11努力創造一個統一的初始化方式。 其語法是使用{}和std::initializer_list ,先看示例。 int values[

C++11 帶來的特性 3—— 關鍵字noexcept

1 關鍵字noexcept 從C++11開始,我們能看到很多程式碼當中都有關鍵字noexcept。比如下面就是std::initializer_list 的預設建構函式,其中使用了noexcept。 constexpr initializer_list() noexcept

C++11 帶來的特性 4—— 匿名函數Lambdas

奇怪 匿名 rand() 函數 列表 print clas exc cpp 1 語法 Lambdas並不是新概念,在其它語言中已經爛大街了。直接進入主題,先看語法: [ captures ] ( params ) specifiers exception attr ->

C++11特性總結列舉+繼承+左右引用+變長模板

一、列舉+斷言+異常 // C++11的一些新的特性 #include "stdafx.h" #include <cassert> using namespace std; // C++

C++11特性:Lambda函式匿名函式

基本的Lambda函式 我們可以這樣定義一個Lambda函式: #include <iostream> using namespace std; int main() { auto func = [] () { c

c++11 特性實戰 :多執行緒操作

# c++11 新特性實戰 (一) ## c++11多執行緒操作 * 執行緒 * **thread** ```c++ int main() { thread t1(Test1); t1.join(); thread t2(Test2);

c++11特性實戰:智慧指標

## c++11新特性實戰(二):智慧指標 c++11添加了新的智慧指標,unique_ptr、shared_ptr和weak_ptr,同時也將auto_ptr置為廢棄(deprecated)。 但是在實際的使用過程中,很多人都會有這樣的問題: 1. 不知道三種智慧指標的具體使用場景 2. 無腦只使用

C++11特性(78)-noexcept運算子(noexcept operator

前一篇文章說明了noexcept說明符,使用了該說明符就相當於對程式設計師和編譯器雙方承諾不會丟擲異常。程式設計師看到這個承諾,可以不必編寫複雜的異常捕捉程式碼;編譯器看到這個承諾,可以執行某些可能丟擲異常時無法進行的優化操作。 異常符說明的實參 前一篇文章沒有提到,實際上noexcep

C++11特性(77)-noexcept異常指示符(Exception Specifier

C++異常處理 異常處理(exception handing)使問題的檢測和處理過程可以分別進行,是C++適用於大規模開發的重要語言特性之一。首先進行簡單說明。 首先假設我們有丟擲某種Error的函式testfun()。   注意:C++並不要求丟擲的物件一定是e

C++11特性(76)-浮點數格式控制(Floating Format Control

前幾篇文章中的某一篇,有一個讀者回復,說我文章的內容C++ Primer上都有。確實是這樣。作者寫作本連載的的目的,首先是參照C++Primer自己學習,然後融入自己的理解並與大家分享。 大師的書當然好,但是具體到每個人不一定一下子都能夠理解。通過作者的文章,大家可以在學習,理解的過程中哪怕

C# 7.0 特性2: 本地方法

本文參考Roslyn專案中的Issue:#259. 簡而言之,【本地方法】就是在方法體內部定義一個方法。 其實咋眼一看,這個新特新並沒有什麼新意,因為目前大量C#的專案中,都可以使用delegate或基於delegate變形的各種方案(lambda, Fun,

C# 7.0 特性1: 基於Tuple的“多”返回方法

本文基於Roslyn專案中的Issue:#347 展開討論. 回顧 首先,提出一個問題,C#中,如何使一個方法可返回”多個”返回值? 我們先來回顧一下C#6.0 及更早版本的做法。 在C#中,通常我們有以下4種方式使一個方法返回多條資料。 使用 KeyVal

C++11特性,實現字串作為switch的case子句

有時候,我們想寫出下面這樣的switch語句: const char* str = "first";  switch(str){  case "first":  cout << "1st one" << endl;