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

C++移動(dòng)操作,RVO和NRVO詳細(xì)

 更新時(shí)間:2021年09月30日 08:53:57   作者:VisualGMQ  
本文將討論了何時(shí)C++會(huì)自動(dòng)進(jìn)行移動(dòng)操作,并且說明了復(fù)制消除,RVO和NRVO優(yōu)的化等香瓜吧資料,需要的小伙伴可以參考一下

移動(dòng)操作主要參考了cppreference 的這個(gè)說明,
優(yōu)化部分的主要的參考來自于stack overflow 的這篇文章

一、移動(dòng)操作

1、移動(dòng)操作有關(guān)的函數(shù)

和移動(dòng)操作相關(guān)的類函數(shù)有兩個(gè)

移動(dòng)構(gòu)造函數(shù):

A(A&& rhs);


移動(dòng)賦值運(yùn)算符:

A& operator=(A&& rhs);


注意這兩個(gè)函數(shù)的參數(shù)類型都不是const,這也是C++默認(rèn)會(huì)生成的函數(shù)聲明。
移動(dòng)構(gòu)造函數(shù)用于在構(gòu)造類型的時(shí)候使用:

A a1;

// 使用std::move強(qiáng)制進(jìn)行移動(dòng)
A a2 = std::move(a1);
或
A a2(std::move(a1));

而移動(dòng)賦值運(yùn)算符就是在賦值的時(shí)候進(jìn)行移動(dòng):

A a1;
A a2;
a1 = std::move(a2); // 使用move進(jìn)行強(qiáng)制移動(dòng)

2、何時(shí)自動(dòng)聲明移動(dòng)構(gòu)造函數(shù)和賦值移動(dòng)構(gòu)造函數(shù)

隱式的移動(dòng)構(gòu)造函數(shù)將會(huì)在可以被生成且滿足如下所有條件的情況下自動(dòng)生成:

  • 沒有用戶聲明的 復(fù)制構(gòu)造函數(shù)
  • 沒有用戶聲明的 復(fù)制賦值運(yùn)算符(即operator=(const A&)這類)
  • 沒有用戶聲明的 移動(dòng)賦值運(yùn)算符(即operator=(A&&)這類)
  • 沒有用戶聲明的 析構(gòu)函數(shù)

所謂可以被生成的意思是滿足以下所有條件:

  • 類中沒有不能移動(dòng)的非靜態(tài)成員
  • 繼承時(shí),基類可以被移動(dòng)
  • 繼承時(shí),基類的構(gòu)造函數(shù)可以被訪問

而移動(dòng)賦值運(yùn)算符的產(chǎn)生條件也差不多,只不過將沒有聲明的 移動(dòng)賦值構(gòu)造函數(shù)改成沒有用戶聲明 移動(dòng)構(gòu)造函數(shù)即可。

總之,這兩個(gè)函數(shù)生成的條件就一句話:除了普通的構(gòu)造函數(shù)外(指默認(rèn)構(gòu)造函數(shù)和帶其他參數(shù)的構(gòu)造函數(shù)),不得聲明任何其他的構(gòu)造函數(shù),operator=函數(shù)和析構(gòu)函數(shù)。

3、何時(shí)自動(dòng)移動(dòng)

使用std::move是一種強(qiáng)制的,顯式的移動(dòng)。但是C++很多時(shí)候?yàn)榱诵蕰?huì)自動(dòng)幫我們移動(dòng)。主要的規(guī)則其實(shí)就是所有的右值都會(huì)進(jìn)行移動(dòng),如果不能移動(dòng),進(jìn)行拷貝。但是為了嚴(yán)謹(jǐn),我們還是擺出cppreference上的規(guī)則:

  • 初始化的時(shí)候使用std::move():T a = std::move(b)或者T a(std::move(b));這種。這里要加上std::move(),不然會(huì)調(diào)用復(fù)制構(gòu)造函數(shù)。
  • 函數(shù)實(shí)參傳遞的時(shí)候使用std::move() :func(std::move(a))
  • 函數(shù)返回時(shí),如:
class A {};

A CreateA() {
 return A();
}

// call

A a = CreateA();

的時(shí)候,使用A()產(chǎn)生的變量會(huì)首先移動(dòng)到CreateA()函數(shù)產(chǎn)生的返回值中,這個(gè)時(shí)候這個(gè)返回值是一個(gè)臨時(shí)變量(我們記為temp),接下來就是執(zhí)行這段代碼:A a = temp,然后temp是臨時(shí)變量, 會(huì)再次調(diào)用A的移動(dòng)構(gòu)造函數(shù)給a變量。

前兩個(gè)是屬于顯式的移動(dòng),最后一種就是隱式移動(dòng)。移動(dòng)賦值運(yùn)算符的規(guī)則也是一樣,只有等號(hào)右邊是臨時(shí)變量就會(huì)自動(dòng)調(diào)用。

二、復(fù)制消除、RVO和NRVO

雖然C++對(duì)移動(dòng)操作定義的很明確,但編譯器卻并不總是按照這個(gè)定義去做。因?yàn)榫幾g器中有三個(gè)重要的優(yōu)化經(jīng)常會(huì)減少拷貝,甚至是移動(dòng)操作。

GCCClang下可以添加-fno-elide-constructors選項(xiàng)來關(guān)閉這三種優(yōu)化。

1、復(fù)制消除

來看一看下面代碼:

class C {
public:
  C() {}
  C(const C&) { std::cout << "A copy was made.\n"; }
  C(C&& rhs) { std::cout << "A move was made.\n"; }

};

C f() {
  return C();
}

int main() {
  std::cout << "Hello World!\n";
  C obj = f();
}

這里建議在C++17標(biāo)準(zhǔn)下編譯,因?yàn)镃++17起所有的復(fù)制消規(guī)則除被寫在語言規(guī)范內(nèi),大部分編譯器應(yīng)該都會(huì)做這件事。我的Clang++ 12.0.5上的執(zhí)行結(jié)果僅僅是輸出了一行Hello World:

Hello World!

按照上面的規(guī)則,函數(shù)在返回的時(shí)候會(huì)進(jìn)行移動(dòng),也就是說在f()的調(diào)用內(nèi),會(huì)先移動(dòng)給臨時(shí)變量,然后臨時(shí)變量再移動(dòng)給obj,但是這里什么都沒發(fā)生,沒有任何的移動(dòng)和拷貝,obj就像憑空出現(xiàn)了一樣。

在C++17起,復(fù)制消除是強(qiáng)制執(zhí)行的,而C++11中是看編譯器心情。
在如下條件下會(huì)進(jìn)行復(fù)制消除:

  • return語句中,return的值是和函數(shù)返回值類型一樣的右值。類型一樣是為了防止隱式轉(zhuǎn)換,否則會(huì)產(chǎn)生新的變量從而阻止移動(dòng),右值是因?yàn)镃++自動(dòng)移動(dòng)只能對(duì)右值操作。
  • 在變量初始化的時(shí)候,初始化表達(dá)式是右值。如:
class A{};

A f() { return A(); } // 這里是第一種情況,會(huì)自動(dòng)復(fù)制消除

// call
A a = f(); // 這里函數(shù)返回值的臨時(shí)變量到a的過程中的移動(dòng)也會(huì)被消除

這也就解釋了為什么上面的代碼沒有調(diào)用任何的拷貝,移動(dòng)函數(shù)了。

2、RVO和NRVO

RVO是Return Value Optimization(返回值優(yōu)化)的簡(jiǎn)寫,而NRVONamed Return Value Optimization(命名返回值優(yōu)化)的簡(jiǎn)寫。這兩個(gè)優(yōu)化是復(fù)制消除的常見形式。
通過他們的名字就可以看出,這是在函數(shù)返回的時(shí)候做的優(yōu)化。

RVO是指在函數(shù)返回一個(gè)臨時(shí)變量時(shí)的優(yōu)化,具體的優(yōu)化如下:

// 原本的函數(shù)
T CreateT(int value) {
 return T(value);
}

T a = CreateT(10);

// 優(yōu)化后的函數(shù)(偽代碼):
void CreateT(T& v, int value) {
 v.T::T(value); // 直接在內(nèi)部進(jìn)行構(gòu)造
}

即通過將要接收函數(shù)返回值的對(duì)象以引用的形式放入函數(shù)內(nèi)部初始化,這樣就避免了一次移動(dòng)/拷貝。

而NRVO則是更加寬泛的RVO。對(duì)于如下的代碼可以執(zhí)行NRVO:

T CreateT(int values) {
 T t(value);
 return t;
}

編譯器也會(huì)優(yōu)化成上面RVO優(yōu)化的樣子。

到此這篇關(guān)于C++移動(dòng)操作,RVO和NRVO詳細(xì)的文章就介紹到這了,更多相關(guān)C++移動(dòng)操作,RVO和NRVO內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++利用LuaIntf調(diào)用Lua的方法示例

    C++利用LuaIntf調(diào)用Lua的方法示例

    這篇文章主要給大家介紹了關(guān)于C++利用LuaIntf調(diào)用Lua以及利用lua-intf來調(diào)用C++函數(shù)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧。
    2017-11-11
  • 詳解C++語言中的加法運(yùn)算符與賦值運(yùn)算符的用法

    詳解C++語言中的加法運(yùn)算符與賦值運(yùn)算符的用法

    這篇文章主要介紹了C++語言中的加法運(yùn)算符與賦值運(yùn)算符的用法,是C++入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2016-01-01
  • C語言中查找字符在字符串中出現(xiàn)的位置的方法

    C語言中查找字符在字符串中出現(xiàn)的位置的方法

    這篇文章主要介紹了C語言中查找字符在字符串中出現(xiàn)的位置的方法,分別是strchr()函數(shù)和strrchr()函數(shù)的使用,需要的朋友可以參考下
    2015-08-08
  • c語言生成隨機(jī)uuid編碼示例

    c語言生成隨機(jī)uuid編碼示例

    這篇文章主要介紹了c語言生成隨機(jī)uuid編碼示例,需要的朋友可以參考下
    2014-05-05
  • Linux?C/C++?timeout命令實(shí)現(xiàn)運(yùn)行具有時(shí)間限制功能

    Linux?C/C++?timeout命令實(shí)現(xiàn)運(yùn)行具有時(shí)間限制功能

    inux?timeout命令的一個(gè)屬性是時(shí)間限制。可以為任何命令設(shè)置時(shí)間限制。如果時(shí)間到期,命令將停止執(zhí)行,這篇文章主要介紹了Linux?C/C++?timeout命令實(shí)現(xiàn)(運(yùn)行具有時(shí)間限制),需要的朋友可以參考下
    2023-02-02
  • gazebo里通過節(jié)點(diǎn)發(fā)布topic讓關(guān)節(jié)轉(zhuǎn)動(dòng)實(shí)現(xiàn)詳解

    gazebo里通過節(jié)點(diǎn)發(fā)布topic讓關(guān)節(jié)轉(zhuǎn)動(dòng)實(shí)現(xiàn)詳解

    這篇文章主要介紹了gazebo里通過節(jié)點(diǎn)發(fā)布topic讓關(guān)節(jié)轉(zhuǎn)動(dòng)實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • C++堆和棧的區(qū)別與聯(lián)系講解

    C++堆和棧的區(qū)別與聯(lián)系講解

    今天小編就為大家分享一篇關(guān)于C++堆和棧的區(qū)別與聯(lián)系講解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-04-04
  • C語言對(duì)于volatile與gcc優(yōu)化的探究

    C語言對(duì)于volatile與gcc優(yōu)化的探究

    這篇文章主要介紹了C語言對(duì)于volatile與gcc優(yōu)化的探究,volatile是一個(gè)特征修飾符(type specifier) volatile的作用是作為指令關(guān)鍵字,確保本條指令不會(huì)因編譯器的優(yōu)化而省略,且要求每次直接讀值。這是百度百科的介紹,那編譯器是具體是怎么優(yōu)化的呢
    2023-02-02
  • Qt實(shí)現(xiàn)自定義日志類的示例代碼

    Qt實(shí)現(xiàn)自定義日志類的示例代碼

    這篇文章主要為大家詳細(xì)介紹了使用 qInstallMessageHandler() 實(shí)現(xiàn)一個(gè)簡(jiǎn)單的日志工具,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以學(xué)習(xí)一下
    2023-12-12
  • C語言實(shí)現(xiàn)隨機(jī)生成6位數(shù)密碼

    C語言實(shí)現(xiàn)隨機(jī)生成6位數(shù)密碼

    這篇文章主要為大家詳細(xì)介紹了如何使用C語言實(shí)現(xiàn)一個(gè)簡(jiǎn)單而實(shí)用的隨機(jī)密碼生成器,該生成器將生成包含字母、數(shù)字和特殊字符的隨機(jī)密碼,有需要的小伙伴可以參考下
    2023-11-11

最新評(píng)論

吉林省| 商河县| 清新县| 黎川县| 图木舒克市| 化州市| 西乌珠穆沁旗| 郎溪县| 望都县| 凌海市| 宁武县| 淮安市| 金秀| 休宁县| 白玉县| 晋州市| 承德市| 池州市| 宕昌县| 田东县| 松江区| 富蕴县| 江源县| 若尔盖县| 阿鲁科尔沁旗| 博客| 乌拉特前旗| 石河子市| 曲阜市| 桑日县| 南安市| 上饶县| 琼海市| 会泽县| 青田县| 建阳市| 宜黄县| 分宜县| 合江县| 嘉义市| 张掖市|