C++右值引用和移動語義

目錄

概念:

左值引用和右值引用

概念:

注意:

左值引用的意義

作函數參數

函數引用返回

右值引用的意義

誕生背景

移動構造

移動賦值

其他應用

萬能引用和完美轉發

默認的移動構造和移動賦值


概念:

左值:顧名思義,可以在等號左邊出現的被叫做左值,左值可以取地址。

右值:只能在等號右邊出現的值為右值,且右值不能取地址。

例如

//左值
int a = 2;
string s="hello";
const int b=3;
int* pa=&a;
//右值
3;//字面常量
a + 2;//表達式
add(2, 3);//函數返回值

左值引用和右值引用

概念:

左值引用是用來引用左值的,給左值起別名:

int a = 2;//左值
int& ra = a;//左值引用

右值引用是用來引用右值的,給右值起別名:

int&& rc = 5;//右值引用

注意:

左值引用只能引用左值,因為如果引用右值會導致權限的放大:

int& ra = 2;//權限放大,編譯錯誤

但是左值引用加上const就可以引用右值:

const int& ra = 2;

右值引用只能引用右值,但是可以引用move后的左值

int a = 2;//左值
int&& ra = move(a);

左值引用的意義

作函數參數

C++引用底層是C語言的指針,所以在作為函數參數時可以減少拷貝或者作為輸出型參數使用。

void func(const string& s)//輸入型參數,const&既可以減少拷貝又可以防止改變引用的實體
{cout << s << endl;
}
void add(int& a)//作為輸出型參數
{a=2;
}

函數引用返回

出了函數棧幀,返回變量不會銷毀的就可以用引用返回,減少拷貝。否則會導致內存越界。

string ss="hello";
const string& func()
{return ss;//ss是全局變量,出函數棧幀不會銷毀,用引用返回就不會生成臨時變量
}

右值引用的意義

誕生背景

普通函數傳值返回時,由于函數棧幀出作用域會銷毀,其內定義的變量會被釋放,所以會返回一個臨時對象,這個臨時對象是要返回對象的拷貝

此時,我們會想:既然局部變量s馬上就要銷毀了,那么我們是否可以將它的資源交換給臨時變量呢,這樣臨時變量的創建就不需要耗費拷貝的代價了

C++把這種即將要銷毀的自定義對象稱為將亡值,在拷貝將亡值的時,可以利用右值引用在拷貝構造和賦值運算符重載函數中接收將亡值,并實現資源的置換,進而減少無意義的拷貝。

移動構造

在拷貝構造的實現中,實現一份形參使用右值引用接收的拷貝構造(即移動構造),當使用將亡值拷貝構造時,編譯器會自動匹配移動構造,在移動構造內實現資源的互換

移動賦值

在賦值運算符重載的實現中,實現一份形參使用右值引用接收的賦值運算符重載(即移動賦值),當使用將亡值賦值時,編譯器會自動匹配移動賦值,在移動賦值內實現資源的互換

C++11后,基本所有的STL容器都新增了移動構造和移動賦值,以此來提高需要深拷貝的容器是將亡值時的拷貝效率。

其他應用

除此之外,右值引用在其他接口中也大放異彩:

STL容器插入數據的接口:當插入需要深拷貝對象的右值時,減少拷貝

std::swap交換函數:

萬能引用和完美轉發

當函數模板和右值引用組合:萬能引用既可以引用左值,又可以引用右值

萬能引用又叫做引用折疊,即傳入右值時&&,傳入左值時折疊&。


右值引用的作用就是限制了接收變量只能是右值,但是右值引用本身會退化為左值:

template<class T>
void func(T&& val)//萬能引用
{cout << val << endl;//就算原本接收的是右值,右值引用val退化為左值
}
int main()
{func(10);return 0;
}

完美轉發:保留對象原生類型屬性,即保持它的左值或者右值的屬性

template<class T>
void func(T&& val)//萬能引用
{cout << std::forward<T>(val) << endl;//這里使用完美轉發保留傳入之前的屬性
}
int main()
{func(10);return 0;
}

默認的移動構造和移動賦值

默認移動構造:

如果你沒有自己實現移動構造函數,且沒有實現析構函數 、拷貝構造、拷貝賦值重載中的任
意一個
。那么編譯器會自動生成一個默認移動構造。默認生成的移動構造函數,對于內置類
型成員會執行逐成員按字節拷貝,自定義類型成員,則需要看這個成員是否實現移動構造,
如果實現了就調用移動構造,沒有實現就調用拷貝構造

解釋:

分析上述定義,默認移動構造就是在析構函數 、拷貝構造、賦值重載都沒有寫,且移動構造也沒有顯式實現的情況下,編譯器會默認生成。

當析構函數,拷貝構造、賦值重載都沒有寫的時候,且默認C++程序員沒有犯錯,那么這個類本身一定只含有內置類型成員或"自控"的自定義類型成員,沒有需要手動釋放的資源。

此時編譯器就要做事了,默認生成一份移動構造,當別人調用默認移動構造,來將自定義類型中可以移動構造的對象自動調用移動構造,增加效率,非常合理。

反著思考:如果一個類內有資源需要手動釋放,那么析構函數 、拷貝構造、賦值重載一定都要手動寫,此時就算我們不手動寫移動構造,編譯器也不會默認生成,因為編譯器不會知道哪些資源需要轉移。

默認移動賦值完全類似。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/46224.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/46224.shtml
英文地址,請注明出處:http://en.pswp.cn/web/46224.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

List數據的幾種數據輸出方式

一、問題引入 在Java中&#xff0c;查詢List集合是一項常見的任務&#xff0c;它可以通過多種方式實現&#xff0c;以滿足不同的需求。下面&#xff0c;List數據的幾種數據輸出方式。 二、實例 /*** 查詢所有用戶信息* return*/ List<User> getAllUser(); <select…

Git【撤銷遠程提交記錄】

在實際開發中&#xff0c;你是否遇到過錯誤的提交了代碼&#xff0c;想要刪掉本次提交記錄的情況&#xff0c;你可以按照如下方法實現。 1、使用 git revert 如果你想要保留歷史記錄&#xff0c;并且對遠程倉庫其他使用者的影響最小&#xff0c;你可以使用 git revert 命令。這…

conda 使用

首先要安裝Miniconda的環境 下面是一下命令關于如何使用conda 查看當前環境列表&#xff1a; conda env list 創建環境不指定路徑&#xff1a; conda create --name p38 python3.8 創建新環境并指定路徑&#xff1a; conda create --prefix /data/p38 python3.8激活新環境&a…

VulnHub:CK00

靶場搭建 靶機下載地址&#xff1a;CK: 00 ~ VulnHub 下載后&#xff0c;在vmware中打開靶機。 修改網絡配置為NAT 處理器修改為2 啟動靶機 靶機ip掃描不到的解決辦法 靶機開機時一直按shift或者esc直到進入GRUB界面。 按e進入編輯模式&#xff0c;找到ro&#xff0c;修…

Kubernetes網絡性能測試-calico插件環境

Kubernetes 網絡性能測試-calico插件環境 本次主要針對calico網絡插件k8s集群的網絡性能進行摸底及測試方法探索實踐。 1. 測試準備 1.1 測試環境 測試環境為VMware Workstation虛擬機搭建的一套K8S環境&#xff0c;版本為1.28.2&#xff0c;網絡插件使用calico&#xff0c…

6Python的Pandas:數據讀取與輸出

Pandas是一個強大的Python數據分析庫&#xff0c;提供了讀取和輸出數據的多種功能。以下是一些常見的數據讀取與輸出方法&#xff1a; 1. 讀取CSV 讀取數據 從CSV文件讀取數據 import pandas as pd# 讀取CSV文件 df pd.read_csv(file_path.csv) print(df.head())從Excel文…

Flutter 狀態管理調研總結

一, 候選狀態管理組件簡介 0. flutter_hooks 一個 React 鉤子在 Flutter 上的實現&#xff1a;Making Sense of React Hooks 鉤子是一種用來管理 Widget 生命周期的新對象&#xff0c;以減少重復代碼、增加組件間復用性&#xff0c;允許將視圖邏輯提取到通用的用例中并重用&…

思路|如何利用oneNote釣魚?

本文僅用于技術研究學習&#xff0c;請遵守相關法律&#xff0c;禁止使用本文所提及的相關技術開展非法攻擊行為&#xff0c;由于傳播、利用本文所提供的信息而造成任何不良后果及損失&#xff0c;與本賬號及作者無關。 本文來源無問社區&#xff0c;更多實戰內容&#xff0c;…

[python]pycharm設置清華源

國內鏡像源有以下幾個&#xff0c;因為都是國內的&#xff0c;基本速度差不了太多。 清華&#xff1a;https://pypi.tuna.tsinghua.edu.cn/simple 阿里云&#xff1a;http://mirrors.aliyun.com/pypi/simple/ 中國科技大學 https://pypi.mirrors.ustc.edu.cn/simple/ 豆瓣&…

針對【module_or_function】的單元測試,全面覆蓋可能的【edge_cases】

針對【module_or_function】的單元測試&#xff0c;全面覆蓋可能的【edge_cases】 編寫單元測試是為了驗證代碼模塊或函數的正確性和魯棒性。對于module_or_function&#xff0c;首先需要確定這個模塊或函數的具體功能和預期輸入范圍。一個好的單元測試應該包括以下幾個步驟&a…

高并發服務器-使用多線程(Multi-Thread)實現【C語言】

在上期的socket套接字的使用詳解中&#xff08;socket套接字的使用詳解&#xff09;最后實現的TCP服務器只能處理一個客戶端的請求發送&#xff0c;當有其他客戶端請求連接時會被阻塞。為了能同時處理多個客戶端的連接請求&#xff0c;本期使用多線程的方式來解決。 程序流程 …

爬蟲案例(讀書網)(下)

上篇鏈接&#xff1a; CSDN-讀書網https://mp.csdn.net/mp_blog/creation/editor/139306808 可以看見基本的全部信息&#xff1a;如(author、bookname、link.....) 寫下代碼如下&#xff1a; import requests from bs4 import BeautifulSoup from lxml import etreeheaders{…

scottplot5 中 使用signalXY圖,如何更新數據?

&#x1f3c6;本文收錄于《CSDN問答解答》專欄&#xff0c;主要記錄項目實戰過程中的Bug之前因后果及提供真實有效的解決方案&#xff0c;希望能夠助你一臂之力&#xff0c;幫你早日登頂實現財富自由&#x1f680;&#xff1b;同時&#xff0c;歡迎大家關注&&收藏&…

總部下達任務時,如何保證員工的執行力?

執行力是個體基于戰略目標&#xff0c;有效整合利用資源&#xff0c;保質保量完成預定目標的操作能力&#xff0c;員工執行力的高低是企業完成效益、成果轉化的關鍵。執行力包含完成任務的意愿、完成能力、完成程度三個維度&#xff0c;其中意愿是基礎和出發點&#xff0c;能力…

物聯網與通信技術

查了很多資料&#xff0c;也夾雜著一些自己的見解。此篇文章僅探討三個問題&#xff1a;物聯網與通信技術的關系&#xff1b;5G為物聯網帶來了什么&#xff0c;物聯網真的需要5G嗎&#xff1b;物聯網發展的現實問題。 1、物聯網與通信技術的關系 最近幾年&#xff0c;物聯網的…

Apache POI 使用Java處理Excel數據 進階

1.POI入門教程鏈接 http://t.csdnimg.cn/Axn4Phttp://t.csdnimg.cn/Axn4P建議&#xff1a;從入門看起會更好理解POI對Excel數據的使用和處理 記得引入依賴&#xff1a; <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactI…

CentOS搭建 Mono 開發環境

Mono 是一個由 Xamarin 公司所主持的自由開放源代碼項目,該項目的目標是創建一系列匹配ECMA標準的.NET工具,包括 C# 編譯器和通用語言架構,Mono項目不僅可以運行于Windows系統上,還可以運行于Linux,FreeBSD,Unix,OS X和Solaris,甚至一些游戲平臺,本實驗帶您搭建 Mono …

Linux chmod 命令簡介

在Linux中&#xff0c;chmod 命令用于改變文件或文件夾的訪問權限。要改變一個文件夾及其內部所有文件和子文件夾的權限&#xff0c;您可以使用遞歸選項 -R。以下是一些常用的 chmod 命令示例&#xff1a; 給所有用戶讀、寫和執行權限&#xff1a; chmod -R 777 /path/to/direc…

JVM高頻面試點

文章目錄 JVM內存模型程序計數器Java虛擬機棧本地方法棧Java堆方法區運行時常量池 Java對象對象的創建如何為對象分配內存 對象的內存布局對象頭實例數據對齊填充 對象的訪問定位 垃圾收集器找到垃圾引用計數法可達性分析&#xff08;根搜索法&#xff09; 引用概念的擴充回收方…

【Socket套接字編程】(實現TCP和UDP的通信)

&#x1f387;&#x1f389;&#x1f389;&#x1f389;點進來你就是我的人了 博主主頁&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳&#xff0c;歡迎大佬指點&#xff01; 人生格言: 當你的才華撐不起你的野心的時候,你就應該靜下心來學習! 歡迎志同道合的朋友…