最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++11 移動構(gòu)造函數(shù)的使用

 更新時間:2022年01月25日 10:08:04   作者:庭樹  
本文主要介紹了C++11 移動構(gòu)造函數(shù)的使用,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下

一、引言

移動構(gòu)造函數(shù)是什么?先舉個例子,你有一本書,你不想看,但我很想看,那么我有哪些方法可以讓我能看這本書?有兩種做法,一種是你直接把書交給我,另一種是我去買一些稿紙來,然后照著你這本書一字一句抄到稿紙上。

顯然,第二種方法很浪費時間,但這正是有些深拷貝構(gòu)造函數(shù)的做法,而移動構(gòu)造函數(shù)便能像第一種做法一樣省時,第一種做法在 C++ 中叫做完美轉(zhuǎn)發(fā)。

二、左值和右值

何為左值?能用取址符號 & 取出地址的皆為左值,剩下的都是右值。

而且,匿名變量一律屬于右值。

int i = 1; // i 是左值,1 是右值

int GetZero {
? ? int zero = 0;
? ? return zero;
}
//j 是左值,GetZero() 是右值,因為返回值存在于寄存器中
int j = GetZero();

//s 是左值,string("no name") 是匿名變量,是右值
string s = string("no name");

三、深拷貝構(gòu)造函數(shù)

用 g++ 編譯器編譯下列代碼時記得加上參數(shù) -fno-elide-constructors。

#include <iostream>
#include <string>

using namespace std;

class Integer {
public:
? ? //參數(shù)為常量左值引用的深拷貝構(gòu)造函數(shù),不改變 source.ptr_ 的值
? ? Integer(const Integer& source)
? ? ? : ptr_(new int(*source.ptr_)) {
? ? ? ? cout << "Call Integer(const Integer& source)" << endl;
? ? }
? ??
? ? //參數(shù)為左值引用的深拷貝構(gòu)造函數(shù),轉(zhuǎn)移堆內(nèi)存資源所有權(quán),改變 source.ptr_ 的值
? ? Integer(Integer& source)
? ? ? : ptr_(source.ptr_) {
? ? ? ? source.ptr_ = nullptr;
? ? ? ? cout << "Call Integer(Integer& source)" << endl;
? ? }
? ??
? ? Integer(int value)
? ? ? : ptr_(new int(value)) {
? ? ? ? cout << "Call Integer(int value)" << endl;
? ? }

? ? ~Integer() {
? ? ? ? cout << "Call ~Integer()" << endl;
? ? ? ? delete ptr_;
? ? }

? ? int GetValue(void) { return *ptr_; }

private:
? ? string name_;
? ? int* ptr_;
};

int
main(int argc, char const* argv[]) {
? ? Integer a(Integer(100));
? ? int a_value = a.GetValue();
? ? cout << a_value << endl;
? ? cout << "-----------------" << endl;
? ? Integer temp(10000);
? ? Integer b(temp);
? ? int b_value = b.GetValue();
? ? cout << b_value << endl;
? ? cout << "-----------------" << endl;

? ? return 0;
}

運行結(jié)果如下。

Call Integer(int value)
Call Integer(const Integer& source)
Call ~Integer()
100
-----------------
Call Integer(int value)
Call Integer(Integer& source)
10000
-----------------
Call ~Integer()
Call ~Integer()
Call ~Integer()

在程序中,參數(shù)為常量左值引用的深拷貝構(gòu)造函數(shù)的做法相當(dāng)于引言中的第二種做法,“重買稿紙”相當(dāng)于再申請一次堆內(nèi)存資源,“重新抄寫”相當(dāng)于把匿名對象 Integer(100) 的資源拷貝到對象 a 這邊;參數(shù)為左值引用的深拷貝構(gòu)造函數(shù)的做法則相當(dāng)于引言中的第一種做法,語句 ptr_(source.ptr_) 和 source.ptr_ = nullptr; 的作用相當(dāng)于“我直接把書拿給你”。

由運行結(jié)果可以看出,當(dāng)同時存在參數(shù)類型為常量左值引用和左值引用的深拷貝構(gòu)造函數(shù)時,匿名對象 Integer(100) 只能選擇前者,非匿名對象 temp 可以選擇后者,這是因為常量左值引用可以接受左值、右值、常量左值、常量右值,而左值引用只能接受左值。因此,對于匿名變量,參數(shù)為任何類型左值引用的深拷貝構(gòu)造函數(shù)都無法實現(xiàn)完美轉(zhuǎn)發(fā)。還有一種辦法——右值引用。

四、右值引用

右值引用也是引用的一種,參數(shù)類型為右值引用的函數(shù)只能接受右值參數(shù),但不包括模板函數(shù),參數(shù)類型為右值引用的模板函數(shù)不在本文討論的范圍內(nèi)。

五、移動構(gòu)造函數(shù)

移動構(gòu)造函數(shù)是參數(shù)類型為右值引用的拷貝構(gòu)造函數(shù)。

在“三”示例程序 Interger 類的定義中添加一個移動構(gòu)造函數(shù),其余保持原樣。

//參數(shù)為左值引用的深拷貝構(gòu)造函數(shù),轉(zhuǎn)移堆內(nèi)存資源所有權(quán),改變 source.ptr_ 的值
Integer(Integer& source)
? : ptr_(source.ptr_) {
? ? source.ptr_ = nullptr;
? ? cout << "Call Integer(Integer& source)" << endl;
}

//移動構(gòu)造函數(shù),與參數(shù)為左值引用的深拷貝構(gòu)造函數(shù)基本一樣
Integer(Integer&& source)
? : ptr_(source.ptr_) {
? ? source.ptr_ = nullptr;
? ? cout << "Call Integer(Integer&& source)" << endl;
}

Integer(int value)
? : ptr_(new int(value)) {
? ? cout << "Call Integer(int value)" << endl;
}

運行結(jié)果如下。

Call Integer(int value)
Call Integer(Integer&& source)
Call ~Integer()
100
-----------------
Call Integer(int value)
Call Integer(Integer& source)
10000
-----------------
Call ~Integer()
Call ~Integer()
Call ~Integer()

只有第二行跟先前不同,匿名對象 Integer(100) 也能通過移動構(gòu)造函數(shù)實現(xiàn)完美轉(zhuǎn)發(fā)。

大家可能會有疑問,上文提及到常量左值引用也可以接受右值,而右值引用也可以接受右值,那一個右值是否有可能會套入一個參數(shù)類型為常量左值引用的函數(shù)呢?答案是不會,一個右值要套入函數(shù)時,會優(yōu)先選擇套入?yún)?shù)類型為右值引用的函數(shù)。

可是仔細(xì)想想還是有點不滿意,如果要讓左值和右值的深拷貝都能實現(xiàn)完美轉(zhuǎn)發(fā),就需要寫兩個內(nèi)容基本一樣的拷貝構(gòu)造函數(shù),一個參數(shù)為(非常量)左值引用,一個參數(shù)為右值,那能不能只用一個函數(shù)就能實現(xiàn)左值、右值兩者的深拷貝完美轉(zhuǎn)發(fā)呢?答案就是強制類型轉(zhuǎn)換,將左值強制強制轉(zhuǎn)換為右值,再套入?yún)?shù)類型為右值引用的深拷貝構(gòu)造函數(shù)。

六、std::move()

std::move() 能把左值強制轉(zhuǎn)換為右值。

我們把語句 Integer b(temp); 改為 Integer b(std::move(temp)); 后,運行結(jié)果如下。

Call Integer(int value)
Call Integer(Integer&& source)
Call ~Integer()
100
-----------------
Call Integer(int value)
Call Integer(Integer&& source)
10000
-----------------
Call ~Integer()
Call ~Integer()
Call ~Integer()

從“10000”的上一行可以看出,std::move() 確實把左值 temp 轉(zhuǎn)換為右值。

七、參考資料

《從4行代碼看右值引用》 博客園用戶“qicosmos(江南)” 著

到此這篇關(guān)于C++11 移動構(gòu)造函數(shù)的使用的文章就介紹到這了,更多相關(guān)C++11 移動構(gòu)造函數(shù)的使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • c++ vector(向量)使用方法詳解(順序訪問vector的多種方式)

    c++ vector(向量)使用方法詳解(順序訪問vector的多種方式)

    vector是向量類型,它可以容納許多類型的數(shù)據(jù),如若干個整數(shù),所以稱其為容器,本文介紹一下使用方法
    2013-12-12
  • C++撲克牌的洗牌發(fā)牌游戲設(shè)計

    C++撲克牌的洗牌發(fā)牌游戲設(shè)計

    這篇文章主要為大家詳細(xì)介紹了C++撲克牌的洗牌發(fā)牌游戲設(shè)計,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-08-08
  • C++ 內(nèi)聯(lián)函數(shù)詳解

    C++ 內(nèi)聯(lián)函數(shù)詳解

    內(nèi)聯(lián)函數(shù)是c++為了提高程序的運行速度做的改進(jìn),本片文章詳細(xì)介紹了C++ 的內(nèi)聯(lián)函數(shù),本文就來詳細(xì)的介紹一下,感興趣的朋友可以了解一下
    2021-11-11
  • C++編程小心指針被delete兩次

    C++編程小心指針被delete兩次

    這篇文章主要介紹了C++編程指針被delete兩次的嚴(yán)重后果,以實例闡述了C++指針使用中的誤區(qū)和注意點,需要的朋友可以參考下
    2014-07-07
  • C++編程語言實現(xiàn)單鏈表詳情

    C++編程語言實現(xiàn)單鏈表詳情

    這篇文章主要介紹的是利用C語言實現(xiàn)單鏈表,實現(xiàn)的是鏈表中最簡單的一種單鏈表且每個結(jié)點中只含有一個指針域,下面將詳細(xì)舉例說明,需要的朋友可以參考一下
    2021-10-10
  • VScode搭建C/C++開發(fā)環(huán)境的詳細(xì)過程

    VScode搭建C/C++開發(fā)環(huán)境的詳細(xì)過程

    最近迷上了vscode,小巧美觀,最主要的是全平臺,但是vscode并不是ide,必須得自己配置環(huán)境,下面這篇文章主要給大家介紹了關(guān)于VScode搭建C/C++開發(fā)環(huán)境的詳細(xì)過程,需要的朋友可以參考下
    2023-06-06
  • C++17使用std::optional表示可能存在的值

    C++17使用std::optional表示可能存在的值

    本文主要介紹了C++17使用std::optional表示可能存在的值,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • C++繼承的賦值轉(zhuǎn)換與菱形虛擬繼承深入詳解

    C++繼承的賦值轉(zhuǎn)換與菱形虛擬繼承深入詳解

    今天我要給大家介紹C++中更深入的內(nèi)容了,C++繼承的賦值轉(zhuǎn)換與菱形虛擬繼承。C++這門語言為了使代碼不冗余,做了些什么操作呢?C++的繼承就很好地實現(xiàn)了類層次的代碼復(fù)用,今天我就要來和大家好好聊一聊它了
    2022-08-08
  • C語言控制進(jìn)程之進(jìn)程等待詳解

    C語言控制進(jìn)程之進(jìn)程等待詳解

    這篇文章主要介紹了C語言控制進(jìn)程之進(jìn)程等待即回收子進(jìn)程的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • C++ push方法與push_back方法常見方法介紹

    C++ push方法與push_back方法常見方法介紹

    push與push_back是STL中常見的方法,都是向數(shù)據(jù)結(jié)構(gòu)中添加元素,本文還將簡述push對應(yīng)的stack與queue系列,常見方法的介紹,以及與push_back相對應(yīng)的vector系列常見方法介紹,感興趣的朋友跟隨小編一起看看吧
    2022-11-11

最新評論

赤城县| 瑞金市| 霍山县| 万宁市| 特克斯县| 玛纳斯县| 乌鲁木齐市| 伊吾县| 唐山市| 苗栗市| 罗定市| 柳州市| 老河口市| 镇巴县| 常德市| 岑巩县| 茌平县| 昌乐县| 宁德市| 商都县| 蓬安县| 苏尼特右旗| 观塘区| 土默特左旗| 崇信县| 威信县| 厦门市| 金山区| 望谟县| 汪清县| 根河市| 莱芜市| 普陀区| 灵山县| 张家港市| 彩票| 桐柏县| 广昌县| 渝中区| 大悟县| 沿河|