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

C++移動操作,RVO和NRVO詳細

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

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

一、移動操作

1、移動操作有關的函數(shù)

和移動操作相關的類函數(shù)有兩個

移動構造函數(shù):

A(A&& rhs);


移動賦值運算符:

A& operator=(A&& rhs);


注意這兩個函數(shù)的參數(shù)類型都不是const,這也是C++默認會生成的函數(shù)聲明。
移動構造函數(shù)用于在構造類型的時候使用:

A a1;

// 使用std::move強制進行移動
A a2 = std::move(a1);
或
A a2(std::move(a1));

而移動賦值運算符就是在賦值的時候進行移動:

A a1;
A a2;
a1 = std::move(a2); // 使用move進行強制移動

2、何時自動聲明移動構造函數(shù)和賦值移動構造函數(shù)

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

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

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

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

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

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

3、何時自動移動

使用std::move是一種強制的,顯式的移動。但是C++很多時候為了效率會自動幫我們移動。主要的規(guī)則其實就是所有的右值都會進行移動,如果不能移動,進行拷貝。但是為了嚴謹,我們還是擺出cppreference上的規(guī)則:

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

A CreateA() {
 return A();
}

// call

A a = CreateA();

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

前兩個是屬于顯式的移動,最后一種就是隱式移動。移動賦值運算符的規(guī)則也是一樣,只有等號右邊是臨時變量就會自動調用。

二、復制消除、RVO和NRVO

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

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

1、復制消除

來看一看下面代碼:

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標準下編譯,因為C++17起所有的復制消規(guī)則除被寫在語言規(guī)范內,大部分編譯器應該都會做這件事。我的Clang++ 12.0.5上的執(zhí)行結果僅僅是輸出了一行Hello World:

Hello World!

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

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

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

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

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

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

2、RVO和NRVO

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

RVO是指在函數(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); // 直接在內部進行構造
}

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

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

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

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

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

相關文章

  • C++利用LuaIntf調用Lua的方法示例

    C++利用LuaIntf調用Lua的方法示例

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

    詳解C++語言中的加法運算符與賦值運算符的用法

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

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

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

    c語言生成隨機uuid編碼示例

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

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

    inux?timeout命令的一個屬性是時間限制??梢詾槿魏蚊钤O置時間限制。如果時間到期,命令將停止執(zhí)行,這篇文章主要介紹了Linux?C/C++?timeout命令實現(xiàn)(運行具有時間限制),需要的朋友可以參考下
    2023-02-02
  • gazebo里通過節(jié)點發(fā)布topic讓關節(jié)轉動實現(xiàn)詳解

    gazebo里通過節(jié)點發(fā)布topic讓關節(jié)轉動實現(xiàn)詳解

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

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

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

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

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

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

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

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

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

最新評論

衡南县| 大余县| 连江县| 迁西县| 庄浪县| 舞阳县| 湟源县| 曲阜市| 锡林浩特市| 兰州市| 南召县| 乌苏市| 商都县| 乐昌市| 澄城县| 安平县| 定远县| 靖江市| 阳谷县| 广水市| 郧西县| 若尔盖县| 吴忠市| 玉环县| 栖霞市| 东安县| 巴青县| 商水县| 巩义市| 平潭县| 特克斯县| 桐庐县| 洛扎县| 宿州市| 甘洛县| 东山县| 黄平县| 友谊县| 历史| 莆田市| 彭州市|