亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C++11的右值引用的具體使用

 更新時(shí)間:2020年02月18日 09:24:34   作者:行者孫  
這篇文章主要介紹了C++11的右值引用的具體使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

C++11 引入了 std::move 語義、右值引用、移動(dòng)構(gòu)造和完美轉(zhuǎn)發(fā)這些特性。由于這部分篇幅比較長(zhǎng),分為3篇來進(jìn)行闡述。

在了解這些特性之前,我們先來引入一些問題。

一、問題導(dǎo)入

  1. 函數(shù)返回值是傳值的時(shí)候發(fā)生幾次對(duì)象構(gòu)造、幾次拷貝?
  2. 函數(shù)的形參是值傳遞的時(shí)候發(fā)生幾次對(duì)象構(gòu)造?

讓我們先來看一段代碼,

// main.cpp
#include <iostream>
using namespace std;

class A{
public:
  A(){
   cout<<"class A construct!"<<endl;
  } 
  A(const A&){
   cout<<"class A copy!"<<endl;
  }
  A& operator=(const A&){
   cout<<"assignment called!"<<endl;
  }
  ~A(){
   cout<<"class A destruct!"<<endl;
  }
};

A get_A_value(){
  return A();
}
int main(){
  A a = get_A_value();
  return 0;
}

使用 g++ 編譯;注意使用 -fno-elide-constructors關(guān)閉省略構(gòu)造優(yōu)化

g++ main.cpp -fno-elide-constructors

可以得到以下輸出

class A construct!
class A destruct!
class A copy!
class A destruct!
class A destruct!

可以看到A a=get_A_value(); 一行代碼居然產(chǎn)生1次對(duì)象構(gòu)造和2次對(duì)象的拷貝構(gòu)造!具體為

  • 在 get_A_value() 里 A() 構(gòu)造了臨時(shí)對(duì)象,發(fā)生了一次構(gòu)造;
  • 函數(shù)返回的時(shí)候會(huì)把臨時(shí)對(duì)象拷貝后作為返回值,發(fā)生一次拷貝;
  • A a = 函數(shù)返回值發(fā)生了拷貝構(gòu)造。

如果使用編譯器優(yōu)化(默認(rèn)), 則會(huì)把臨時(shí)對(duì)象拷貝的那次 和 用返回值構(gòu)造最終對(duì)象的拷貝的給省略了;也即,只有一次拷貝和析構(gòu)。

class A construct!
class A destruct!

如果把上面代碼改一下

// ... A

void pass_A_by_value(A a){

}
int main(){
  A a;
  pass_A_by_value(a);
  return 0;
}

在去掉優(yōu)化 g++ main.cpp -fno-elide-constructors時(shí)輸出為

class A construct!
class A copy!
class A destruct!
class A destruct!

1次構(gòu)造加上1次拷貝。

因此,下次如果面試的時(shí)候有人問這個(gè)問題,你就可以說:默認(rèn)情況下經(jīng)過編譯器優(yōu)化后臨時(shí)對(duì)象的拷貝就會(huì)被省去,如果使用 -fno-elide-constructors 省略優(yōu)化,則還要考慮臨時(shí)對(duì)象的拷貝。

事實(shí)上,在未經(jīng)優(yōu)化的情況下,以下時(shí)候拷貝構(gòu)造函數(shù)會(huì)被調(diào)用:

  1. 函數(shù)內(nèi)的局部對(duì)象做為返回值返回(不是引用)的時(shí)候會(huì)發(fā)生拷貝(拷貝為臨時(shí)對(duì)象返回)
  2. 函數(shù)形參為傳值的時(shí)候,會(huì)發(fā)生拷貝構(gòu)造
  3. 一個(gè)對(duì)象以另外一個(gè)對(duì)象進(jìn)行初始化的時(shí)候

對(duì)象的頻繁構(gòu)造是程序的開銷,特別是當(dāng)對(duì)象內(nèi)部有堆上內(nèi)存(比如有 new 出來的成員)的時(shí)候,每次拷貝構(gòu)造的時(shí)候都需要用 new 申請(qǐng)一塊內(nèi)存,造成性能的降低。對(duì)于情況2,好習(xí)慣是如果函數(shù)參數(shù)是只讀的(也即不會(huì)在程序內(nèi)進(jìn)行修改),傳引用作為參數(shù),也即 pass_A_by_refrence(const A &a); 對(duì)于情況1,編譯器會(huì)為我們進(jìn)行優(yōu)化; 對(duì)于情況3,C++11 引入了一種移動(dòng)構(gòu)造函數(shù)的概念,它將獲取**右值引用*,右值的“資源” move 到新對(duì)象中,這個(gè)過程中不會(huì)申請(qǐng)新的內(nèi)存,從而達(dá)到提高了效率和性能。

所以,要理解些關(guān)鍵詞 “移動(dòng)構(gòu)造”、“移動(dòng)語義” ,首先要理解右值和右值引用。

二、右值和右值引用

2.1 左值(lvalue)和右值(rvalue)

在 一、問題導(dǎo)入 里我們提到了臨時(shí)對(duì)象,也即函數(shù)返回值的時(shí)候只會(huì)“臨時(shí)”存在的對(duì)象(運(yùn)行超過那一行就會(huì)結(jié)束它的生存期),這個(gè)臨時(shí)返回值就是一個(gè)右值;
右值的最直觀的定義為,顧名思義:

位于賦值運(yùn)算符 = 右邊的值,為右值;在左邊的則為左值

A a = foo(); // foo() 為右值
char *x = "thu"; // “thu”為字面值也為右值
a = b + c; // b + c這個(gè)結(jié)果也是一個(gè)右值

在C++中,還有個(gè)定義為:

左值可以取得地址、有名字; 不可以取得地址、沒有名字的為右值。

所以 A a = foo()可以用 &a取得a的地址,a 是左值,然是不能取得 foo()的地址,(&foo())無法通過編譯, foo()返回的臨時(shí)對(duì)象也是沒有名字的,所以是右值。

在C++11中,右值包括兩種,一中是將亡值(xvalue, eXpiring Value),一種是純右值(prvalue,Pure Rvalue)[1]。函數(shù)非引用返回的臨時(shí)對(duì)象、運(yùn)算表達(dá)式的結(jié)果、1, 3.14,'c'這樣的字面值等都屬于純右值。而xvalue則是由 C++11引入的 如返回值為 A&& 的函數(shù)返回值或者std::move()的返回值等。

不深究的話,我們只需要知道左值和右值的區(qū)別就行了。對(duì)于右值的詳細(xì)分類則不必深究。

2.2 左值引用和右值引用

左值引用就是一般的引用,一般用一個(gè)&表示,例如

const A &a_ref = a; // 取得對(duì)象 a 的引用

左值引用相當(dāng)于別名,指向一個(gè)具體的對(duì)象。

右值引用

右值引用顧名思義,就是右值的引用, 用 &&表示;
A &&r_ref = getRvalue(); // r_ref 是一個(gè)右值引用
右值引用也相當(dāng)于別名,與左值的區(qū)別為右值引用是無名變量的別名。

getRvalue() 是一個(gè)返回右值的函數(shù),右值在這一句執(zhí)行完就該結(jié)束他的生存期了,如果是對(duì)象就該調(diào)用析構(gòu)函數(shù)了;但是==右值引用讓它強(qiáng)行續(xù)命==;使用右值引用指向右值,右值的生存期和右值引用一樣長(zhǎng)了,這也就少一次對(duì)象的析構(gòu)和構(gòu)造了。

C++的右值引用主要有兩個(gè)用處,一個(gè)是移動(dòng)語義,一個(gè)是完美轉(zhuǎn)發(fā)。這個(gè)將在接下來的兩篇來講。

總結(jié)

為了導(dǎo)入右值和移動(dòng)語義,首先復(fù)習(xí)了以下臨時(shí)對(duì)象在函數(shù)返回值和傳參數(shù)時(shí)構(gòu)造了幾次;然后對(duì)比介紹了左值和右值,以及右值引用的形式和含義。為移動(dòng)語義和完美轉(zhuǎn)發(fā)的介紹做鋪墊。

參考資料

Michale Wang| IBM XL 編譯器中國(guó) 《深入理解C++11》, 機(jī)械工業(yè)出版社

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • C++ STL_vector 迭代器失效問題的解決方法

    C++ STL_vector 迭代器失效問題的解決方法

    迭代器的主要作用就是讓算法能夠不用關(guān)心底層數(shù)據(jù)結(jié)構(gòu),其底層實(shí)際就是一個(gè)指針,或者是對(duì)指針進(jìn)行了封裝,迭代器失效,實(shí)際就是迭代器底層對(duì)應(yīng)指針?biāo)赶虻目臻g被銷毀了,對(duì)迭代器失效我們了解了,那么現(xiàn)在我們就分析,在vector中哪些操作會(huì)導(dǎo)致迭代器失效
    2023-08-08
  • VC++的if語句應(yīng)用范圍分析

    VC++的if語句應(yīng)用范圍分析

    這篇文章主要介紹了VC++的if語句應(yīng)用范圍分析,對(duì)VC++初學(xué)者有很好的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2014-08-08
  • C語言安全編碼數(shù)組記法的一致性

    C語言安全編碼數(shù)組記法的一致性

    這篇文章主要介紹了C語言安全編碼數(shù)組記法的一致性,需要的朋友可以參考下
    2014-07-07
  • C語言指針的長(zhǎng)度和類型深入分析

    C語言指針的長(zhǎng)度和類型深入分析

    這篇文章主要介紹了C語言指針的長(zhǎng)度和類型,針對(duì)常見的各個(gè)類型進(jìn)行了相對(duì)詳細(xì)的分析,需要的朋友可以參考下
    2014-09-09
  • Qt基礎(chǔ)開發(fā)之QString與QByteArray詳細(xì)用法與區(qū)別及QString QByteArray互轉(zhuǎn)

    Qt基礎(chǔ)開發(fā)之QString與QByteArray詳細(xì)用法與區(qū)別及QString QByteArray互轉(zhuǎn)

    這篇文章主要介紹了Qt基礎(chǔ)開發(fā)之QString與QByteArray詳細(xì)用法與區(qū)別及QString QByteArray互轉(zhuǎn),需要的朋友可以參考下
    2020-03-03
  • C++單例模式的實(shí)例詳解

    C++單例模式的實(shí)例詳解

    這篇文章主要介紹了C++單例模式的實(shí)例詳解的相關(guān)資料,希望通過本文能幫助到大家,讓大家掌握這部分內(nèi)容,需要的朋友可以參考下
    2017-10-10
  • 深入C語言內(nèi)存區(qū)域分配(進(jìn)程的各個(gè)段)詳解

    深入C語言內(nèi)存區(qū)域分配(進(jìn)程的各個(gè)段)詳解

    一般情況下,一個(gè)可執(zhí)行二進(jìn)制程序(更確切的說,在Linux操作系統(tǒng)下為一個(gè)進(jìn)程單元,在UC/OSII中被稱為任務(wù))在存儲(chǔ)(沒有調(diào)入到內(nèi)存運(yùn)行)時(shí)擁有3個(gè)部分,分別是代碼段(text)、數(shù)據(jù)段(data)和BSS段。這3個(gè)部分一起組成了該可執(zhí)行程序的文件
    2013-07-07
  • C++ Boost.Range與Adapters庫使用詳解

    C++ Boost.Range與Adapters庫使用詳解

    這篇文章主要介紹了C++ Boost.Range與Adapters庫使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-11-11
  • C++使用宏實(shí)現(xiàn)動(dòng)態(tài)庫加載

    C++使用宏實(shí)現(xiàn)動(dòng)態(tài)庫加載

    開發(fā)的時(shí)候,有些項(xiàng)目不能靜態(tài)鏈接動(dòng)態(tài)庫,需要程序運(yùn)行時(shí)加載動(dòng)態(tài)庫。本文將使用宏來實(shí)現(xiàn)動(dòng)態(tài)庫的加載,感興趣的小伙伴可以跟隨小編一起了解一下
    2022-12-12
  • C語言實(shí)現(xiàn)簡(jiǎn)易掃雷程序

    C語言實(shí)現(xiàn)簡(jiǎn)易掃雷程序

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)簡(jiǎn)易掃雷程序,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-07-07

最新評(píng)論