在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

聊聊std::move函數和std::forward函數

CPP開發者 ? 來源:雨樂聊編程 ? 2024-11-05 16:58 ? 次閱讀

以下文章來源于雨樂聊編程,作者雨樂

今天我們聊聊Modern cpp的兩個非常重要的概念移動語義轉發引用

概念

值類別

C++11之前,值類別分為左值和右值兩種,但是自C++11起,引入了純右值,消亡值兩種。其中,左值和將亡值合稱為泛左值,純右值和將亡值合稱為右值(C++11之前的右值等同于C++11中的純右值)。因為本文目的不在于分析值類別,所以本文意義中的左值和右值就是字面意義上的左值右值。

右值(RVALUE),即立即創建和使用的臨時值。在C++中,右值是與內存地址無關的表達式,這意味著其沒有地址,也不能被修改。通常3、1.0以及std::string("abc")這種都屬于右值。

PS:需要注意的是常量字符串"abc"等這種屬于左值。

與右值相反,左值(LVALUE),其具有內存地址和可修改,其可以用于分配新值或者獲取對象的地址。

可能有人有疑問,就是如何區分左值和右值,目前一個比較通用的判斷方式就是:判斷其是否可以取地址

左值引用 & 右值引用

既然有左值和右值,那么相應的,也就存在左值引用右值引用,常常如下這種表示:

inta=0;
int&la=a;
int&&r=3;

在上述示例中,a、la以及r都屬于左值,其中la是左值引用,r是右值引用。

看下面一個例子:

#include

voidPrint(int&lref){
std::cout<

上述示例輸出如下:

Lvaluereference
constLvaluereference
Rvaluereference

std::move

std::move是C++中的一個常用函數,它執行到右值引用的轉換,允許您將左值轉換為右值。這在您想要轉移所有權或啟用對象的移動語義的情況下非常有用。移動語義允許開發人員有效地將資源(如內存或文件句柄)從一個對象傳輸到另一個對象,而無需進行不必要的復制。

正如字面意義所理解的,移動語義允許將對象有效地從一個位置“移動”到另一個位置,而不是復制,這對于管理資源的對象特別有用。它實際上并沒有移動任何東西;它只是將表達式的類型更改為右值引用。這允許調用移動構造函數或移動賦值運算符,而不是調用復制構造函數或復制賦值運算符。

gcc對move的實現如下:

template
inlinetypenamestd::remove_reference<_Tp>::type&&
move(_Tp&&__t)
{returnstatic_cast::type&&>(__t);}

也就是說,其僅僅通過static_cast<>做了類型轉換~

std::move僅僅將對象轉換為右值引用,僅此而已

#include
#include

classObj{
public:
Obj(){
std::cout<

輸出如下:

Defaultconstructor
Moveconstructor
Defaultconstructor
Moveassignmentoperator

在上述示例中:

?Obj1創建對象并調用構造函數?obj2是通過使用std::move移動obj1創建的,它調用移動構造函數?創建obj3并調用默認構造函數?當使用std::move將obj2移動到 obj3 時,將調用移動賦值運算符

在此示例中,使用std::move操作, obj1到obj2 以及 obj2到obj3調用的是移動的行為,這樣可以提高性能,尤其是在移動大型數據結構或資源時。但是,重要的是要注意移動對象的狀態及其擁有的資源。

#include
#include

classObj{
public:
Obj(){
std::cout<p1=std::make_unique();

std::unique_ptrp2=std::move(p1);
if(p1){
std::cout<fun();

return0;
}

在這個例子中,首先創建了一個類型為std::unique_ptr的指針p1,然后通過調用std::move()將p1的所有權轉移至p2,接著判斷p1是否為有效的指針,如果是則輸出,接著p2調用fun()函數。

上述示例輸出結果如下:

Objconstructed
infun
Objdestructed

從這個輸出結果可以看出,通過std::move()將所有權從p1轉移至p2后,p1不再持有任何資源。

std::forward

std::forward是 C++ 標準庫中的一個函數模板,用于在模板函數中進行完美轉發。它允許在模板函數中將參數轉發到另一個函數,同時保持參數的值類別(value category)和 cv 限定符(const 或 volatile 限定符)不變。

std::forward通常與右值引用(&&)結合使用,用于轉發傳遞給模板函數的參數。在模板函數內部,你可以使用std::forward來將參數轉發給其他函數,并保持原始參數的性質。

示例如下:

#include

voidPrint(constint&lref){
std::cout<
voidFun(T&&param){
Print(std::forward(param));
}

intmain(){
intx=5;
constinty=10;

Fun(x);//lvaluereference
Fun(y);//lvaluereference
Fun(20);//rvaluereference

return0;
}

在這個例子中,我們創建了一個模板函數Fun(),其參數類型為T&&,當使用左值調用Fun()時候,它將param作為左值進行轉發,當使用右值調用Fun()時候,它將param作為右值進行轉發,然后調用對應的函數,這樣可保證在不損失真實類型的情況下調用正確的函數。

move vs forward

對于第一次接觸這塊知識點的開發人員來說,可能有點疑惑,是否可以用move來替代forward,我們且看一個例子,相信你看了之后就不會對這塊一目了然:

#include


voidPrint(int&a){
std::cout<
voidfunc1(T&&a){
Print(std::move(a));
}


template
voidfunc2(T&&a){
Print(std::forward(a));
}

intmain(){
intarg=10;

std::cout<

上述代碼輸出如下:

Callingfunc1withstd::move()...
int&&:10
int&&:25
Callingfunc2withstd::forward()...
int&:10
int&&:25

在上述代碼中:

?創建了兩個重載函數Print,其參數類型分別為**int &和int &&**,函數的功能是輸出其參數的類型

?模板函數func1(),函數參數a為轉發引用(T&&,也有地方稱之為萬能引用),函數體內調用參數為std::move(a)的Print()函數,將a轉換為右值引用,這意味著,如果a是左值,則傳遞給Print()函數的參數類型為右值引用

?模板函數func2(),與模板函數func1()一樣,該函數也采用轉發引用(T&&)。但是,它使用 std::forward來保留a的原始值類別。這意味著如果a是左值,它將作為左值傳遞給Print()函數,如果它是右值,它將作為右值傳遞

?在 main() 中,使用左值和右值調用函數func1和func2,以觀察對應的行為

通過上面輸出,基本可以區分這倆,在此,做下簡單的總結:

?目的

?std::forward:用于完全按照傳遞的參數轉發,保留其值類別(左值或右值)

?std::move:用于將對象轉換為右值引用,通常用于啟用移動語義并轉移所有權

?用法

?std::forward:通常用于轉發引用(通用引用),以保留傳遞給另一個函數的參數的值類別

?std::move:用于將對象顯式轉換為右值引用

?影響

?std::forward:不更改參數的值類別。如果原始參數是右值引用,則它返回右值引用,否則返回左值引用

?std::move:將其參數轉換為右值引用,將其值類別更改為右值

?安全

?std::forward:可以安全地與轉發引用 (T&&) 一起使用,以確保正確轉發參數,而不會產生不必要的副本。

?std::move:應謹慎使用,因為它可能會導致從其他地方仍需要的對象移動,從而導致未定義的行為

?場景

?std::forward:用于需要完美轉發參數的場景,例如模板函數和類中。

?std::move:在顯式轉移所有權或調用移動語義時使用,例如從函數返回僅移動類型時

?返回類型

?std::forward:返回類型取決于傳遞給它的參數的值類別,它可以返回左值引用或右值引用。

?std::move:始終返回右值引用

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 內存
    +關注

    關注

    8

    文章

    3025

    瀏覽量

    74042
  • 字符串
    +關注

    關注

    1

    文章

    579

    瀏覽量

    20514
  • 函數
    +關注

    關注

    3

    文章

    4331

    瀏覽量

    62609
  • C++
    C++
    +關注

    關注

    22

    文章

    2108

    瀏覽量

    73646

原文標題:性能大殺器:std::move 和 std::forward

文章出處:【微信號:CPP開發者,微信公眾號:CPP開發者】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    SAC-STD標準

    本帖最后由 eehome 于 2013-1-5 09:48 編輯 那位工程師有關于SAC-STD-001 Certification StandardSAC-STD-002 Audit
    發表于 11-17 18:57

    std::inner_product函數運算特別緩慢如何優化?

    ();for(,,,)std::inner_product(samples);i2s_write(samples);結果就是,inner_product占用了大量的時間,導致音頻沒有辦法及時的處理,在esp32 Lyra-T
    發表于 02-15 08:11

    如何使用std::future/std::promise 和 std::packaged_task來促進esp32上的多線程?

    我正在考慮使用 std::future/std::promise 和 std::packaged_task 來促進 esp32 上的多線程。我知道多任務函數之間的抽象分層如下:
    發表于 03-02 08:44

    IEEE Std C37.09-1999標準

    IEEE Std C37.09™-1999(Revision ofIEEE Std C37.09-1979) Errata toIEEE Standard Test Procedure
    發表于 07-24 22:18 ?12次下載

    IEEE Std 802.1ad-2005標準

    IEEE Std 802.1ad™-2005(Amendment toIEEE Std 802.1QTM-2005)IEEE Standard forLocal
    發表于 07-27 18:20 ?62次下載

    IEEE Std C57.12.37™-2006

    IEEE Std C57.12.37™-2006(Revision ofIEEE Std 1388™-2000)IEEE Standard
    發表于 07-27 18:28 ?16次下載

    IEEE STD C57.12.59-2001標準

    IEEE STD C57.12.59-2001標準,IEEE STD C57.12.59-2001標準
    發表于 07-27 18:32 ?27次下載

    IEEE Std C57.12.90™-2006

    IEEE Std C57.12.90TM-2006(Revision ofIEEE Std C57.12.90-1999)IEEE Standard Test Codefor
    發表于 07-27 18:33 ?54次下載

    IEEE Std 1226-1998

    IEEE Std 1226-1998(Revision ofIEEE Std 1226-1993)IEEE ABBET™IEEE Trial-Use Standard for A
    發表于 08-11 23:46 ?26次下載

    IEEE Std C37.081a-1997

    IEEE Std C37.081a-1997(Supplement to IEEE Std C37.081-1981)Supplement to IEEE Guide
    發表于 08-11 23:50 ?21次下載

    一篇“非典型”面試經驗貼在Reddit上引發熱議

    你的代碼中:包括模板、繼承、指針,引用,std :: vector,std :: unordered_map,std :: move,std
    的頭像 發表于 04-30 08:48 ?2704次閱讀

    std::function簡介及模板類聲明

    01 — std::function簡介 std::function是一個函數包裝器,該函數包裝器模板能包裝任何類型的可調用實體,如普通函數
    的頭像 發表于 07-28 15:30 ?4823次閱讀

    在C++中如何用虛函數實現多態

    。 // virtual_function.cpp : 此文件包含 “main” 函數。程序執行將在此處開始并結束。 // #include 《iostream》 class Base { public: Base() { std
    的頭像 發表于 09-29 14:18 ?1699次閱讀

    C++ std::tie函數的作用和用法

    C++中std::tie函數的作用就是從元素引用中生成一個tuple元組,其在頭文件中定義
    的頭像 發表于 07-18 17:28 ?852次閱讀

    動態數組和C++ std::vector詳解

    std::vector是C++的默認動態數組,其與array最大的區別在于vector的數組是動態的,即其大小可以在運行時更改。std::vector是封裝動態數組的順序容器,且該容器中元素的存取是連續的。
    的頭像 發表于 07-19 11:07 ?974次閱讀
    主站蜘蛛池模板: 日本免费一区二区视频| 手机看片自拍自拍自拍| aaaa大片| 天天干天| 亚综合| 中文字幕有码视频| 亚州色吧| 免费手机黄色网址| 成年人激情视频| 91在线影视| 久久久婷婷| 毛片大全在线| 一级视频在线免费观看| 九九国产精品视频| 中国一级做a爰片久久毛片| 久久综合久色欧美婷婷| 亚洲精品网站日本xxxxxxx| 国产精品国产午夜免费福利看| 亚洲免费网站在线观看| 午夜精品久久久久蜜桃| 萌白酱香蕉白丝护士服喷浆| 手机看片1024在线| 很黄很暴力 很污秽的小说| 可以直接看的黄址| 国产亚洲精品成人一区看片| 日本一区二区在线不卡| 欧美精品国产第一区二区| 奇米影视四色7777久久精品| 91精品啪在线观看国产日本| 起碰免费视频| 97色偷偷| 人人澡人人人人夜夜爽| 久久国产精品99久久久久久老狼 | 在线视频影院| 亚洲第一区视频| 色视频在线观看免费| 天天操夜夜夜| 亚洲国产成人精品女人久久久| 久久综合五月开心婷婷深深爱| 国产精品天天影视久久综合网| 深爱五月网|