C++臨時對象生命周期

引言

朋友問了我一段代碼:

const string & foo(const string & a, const string & b)
{return a.empty() ? b : a;
}
int main ()
{auto & s = foo("", "foo"); // auto is const stringcout << s << '\n';return 0;
}

可以思考一下上面的代碼能否通過編譯?如果可以會輸出什么?

UB

對于上面的代碼,是可以通過編譯的。使用GCC的話輸出foo,那么代碼似乎沒有問題。
其實不然,上述的代碼發生了UB(UB是Undefined Behaviour的縮寫,意思是未定義行為既具體會發生什么由編譯器的實現決定沒有官方的要求)。
我們將上面的代碼稍作更改:

const string & foo(const string & a, const string & b)
{return a.empty() ? b : a;
}
int main ()
{auto & s = foo("", "foo"); // auto is const stringint a[100] = {0};cout << s << '\n';return 0;
}

在使用GCC的情況下,上面的代碼輸出了空串。

為什么?臨時對象的生命周期

要知道為什么會出現上面的問題,我們需要先了解臨時對象的生命周期。

  • 臨時對象:臨時對象往往是指右值(純右值和將亡值)。
  • 生命周期:一個對象的生命周期可以理解為從調用構造函數開始到調用析構函數結束的整個過程。

當一個對象的生命周期結束后(調用析構函數后)其不能再被繼續使用否則會發生未定義行為。
例如:通過new申請的對象,在delete之后繼續進行解引用,此時會發生未定義行為(訪問野指針)。
對于上面提到的代碼實際上,在輸出的時候,"""foo"的生命周期已然結束,所以出現了未定義行為,這是因為在string中用于存放數據的內存已經被回收了(臨時對象調用過析構函數),但是s中依然有指向數據的指針(或者引用),當沒有數據對對應地址進行寫操作的時候,依然能夠讀出之前的數據,但是增加int a[100] = {0}之前的內存已經被覆蓋,因此此時輸出空串(但實際上由于是UB此時發生什么都是可以的,這里只是在根據結果解釋)。
一個問題:string不是存放在堆上嗎,而申請的int a[100]存放在棧上,為什么可以覆蓋堆上的內容?

C++string的長度大于某個值時(這個值可能是16),其數據才回被放置在堆上,否則還是存放在棧上。同時string中存放著在棧上的數據,例如字符串長度變量,以及指針存放在棧上(使用new可以使其存放在堆上),通過int a[100] = {0}可以使長度清0和指針變成空指針。

簡單說明了上面代碼的問題之后,知道了是因為臨時對象已經被析構了,導致其發生了未定義行為。那么,臨時對象的生命周期究竟如何呢?

  • 對于沒有綁定對引用的臨時變量其創建完成后,即開始進行析構。例如string("aaa");從該語句的下一行開始,臨時變量已經被析構。需要注意的是:string a = string("aaa");實際上會調用移動構造函數,所以該臨時變量已經綁定到引用上了,此時不屬于未綁定到引用上的臨時變量。
  • 對于綁定到引用的臨時變量,其生命周期在引用脫離作用域時結束。例如:
    {string &&a = string("xxx");	
    } // string("xxx") is finalized here.
    
  • 特殊地,對于將同一個臨時變量綁定到兩個不同的引用上,其生命周期以第一個引用為準。例如:
    {string &&a = string("xxx");{string &&b = std::move(a);}// using a here is OK
    } // string("xxx") is finalized here.
    

所以對于引言中的例子,在函數返回之后返回值賦值之前,臨時變量已經被析構了。

參考

Lifetime of a temporary cppreference

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

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

相關文章

第二百回 如何獲取App自身的信息

文章目錄 1. 概念介紹2. 使用方法2.1 ClipOval2.2 ClipRRect 3. 示例代碼 我們在上一章回中介紹了AspectRatio Widget相關的內容&#xff0c;本章回中將介紹剪裁類組件(Clip).閑話休提&#xff0c;讓我們一起Talk Flutter吧。 1. 概念介紹 我們在這里說的剪裁類組件主要是指對…

dockerfile---創建鏡像

dockerfile創建鏡像&#xff1a;創建自定義鏡像。 包擴配置文件的創建&#xff0c;掛載點&#xff0c;對外暴露的端口。設置環境變量。 docker鏡像的方式: 1、基于官方源進行創建 根據官方提供的鏡像源&#xff0c;創建鏡像&#xff0c;然后拉起容器。是一個白板&#xff0c…

初識人工智能,一文讀懂強化學習的知識文集(5)

&#x1f3c6;作者簡介&#xff0c;普修羅雙戰士&#xff0c;一直追求不斷學習和成長&#xff0c;在技術的道路上持續探索和實踐。 &#x1f3c6;多年互聯網行業從業經驗&#xff0c;歷任核心研發工程師&#xff0c;項目技術負責人。 &#x1f389;歡迎 &#x1f44d;點贊?評論…

2023年運營級網賺網盤平臺搭建指南(包含源碼和教程)

源碼介紹 為什么要考慮自己搭建網盤呢&#xff1f;現如今&#xff0c;許多大型網盤平臺都對文件添加了各種限制&#xff0c;導致很多文件容易被刪除。而且&#xff0c;大部分網盤還會限制下載速度&#xff0c;如果沒有開通VIP會員&#xff0c;使用起來非常不便。 本指南提供了…

免費節假日api接口使用教程-聚合數據

免費節假日api接口使用教程-聚合數據 文章目錄 &#x1f4d6;訪問官網&#x1f330;例子完整代碼&#x1f58a;?最后總結 &#x1f4d6;訪問官網 聚合數據 官網地址 https://dashboard.juhe.cn/home 點擊api 接口文檔 &#x1f330;例子 get方式 curl -k -i -d “key您申請…

解決Git提交錯誤分支

如果 Git 提交到錯誤的分支&#xff0c;可以通過以下步驟將其轉移到正確的分支上&#xff1a; 1.檢查當前所在的分支&#xff0c;可以通過 git branch 命令查看。 git branch2.切換到正確的分支&#xff0c;可以通過 git checkout <正確的分支名> 命令進行切換。 git …

vue使用echarts顯示中國地圖

項目引入echarts以后&#xff0c;在頁面創建canvas標簽 引入一個公共js文件&#xff08;下面這段代碼就是china.js文件&#xff09; (function (root, factory) {if (typeof define function && define.amd) {// AMD. Register as an anonymous module.define([ex…

【EXCEL】折線圖添加垂直x軸的豎線|畫圖

相關鏈接&#xff1a;excel 添加垂直豎向直線 如何在Excel中添加水平和垂直線&#xff1f; 因為加輔助列有點不習慣&#xff0c;已經有分位數橫坐標了&#xff0c;想著試下用散點圖的誤差線畫 效果圖&#xff1a; 步驟&#xff1a; s1&#xff1a;隨便框選兩列數據–>插入(…

大創項目推薦 卷積神經網絡手寫字符識別 - 深度學習

文章目錄 0 前言1 簡介2 LeNet-5 模型的介紹2.1 結構解析2.2 C1層2.3 S2層S2層和C3層連接 2.4 F6與C5層 3 寫數字識別算法模型的構建3.1 輸入層設計3.2 激活函數的選取3.3 卷積層設計3.4 降采樣層3.5 輸出層設計 4 網絡模型的總體結構5 部分實現代碼6 在線手寫識別7 最后 0 前言…

深入理解JavaScript異步編程與Promise

異步編程的背景 在Web開發中&#xff0c;異步編程是為了解決JavaScript的單線程執行模型導致的阻塞問題。異步編程允許程序在等待某些操作完成的同時&#xff0c;繼續執行其他任務&#xff0c;提高了程序的效率和響應速度。 回調地獄與Promise的誕生 回調地獄是異步編程中一…

Unity中實現ShaderToy卡通火(一)

文章目錄 前言一、準備好我們的后處理基礎腳本1、C#&#xff1a;2、Shader&#xff1a; 二、開始逐語句對ShaderToy進行轉化1、首先&#xff0c;找到我們的主函數 mainImage2、其余的方法全部都是在 mainImage 函數中調用的方法3、替換后的代碼(已經沒報錯了&#xff0c;都是效…

智能優化算法應用:基于正余弦算法3D無線傳感器網絡(WSN)覆蓋優化 - 附代碼

智能優化算法應用&#xff1a;基于正余弦算法3D無線傳感器網絡(WSN)覆蓋優化 - 附代碼 文章目錄 智能優化算法應用&#xff1a;基于正余弦算法3D無線傳感器網絡(WSN)覆蓋優化 - 附代碼1.無線傳感網絡節點模型2.覆蓋數學模型及分析3.正余弦算法4.實驗參數設定5.算法結果6.參考文…

基于單個參數線性回歸的機器學習代碼

本文為學習吳恩達版本機器學習教程的代碼整理&#xff0c;使用的數據集為https://github.com/fengdu78/Coursera-ML-AndrewNg-Notes/blob/f2757f85b99a2b800f4c2e3e9ea967d9e17dfbd8/code/ex1-linear%20regression/ex1data1.txt 將數據集和py代碼放到同一目錄中&#xff0c;使…

2023最新八股文前端面試題

第一章 Css 1.說一下CSS的盒模型。 在HTML頁面中的所有元素都可以看成是一個盒子盒子的組成:內容content、內邊距padding、邊框border、外邊距margin盒模型的類型: 標準盒模型 margin border padding content IE盒模型 margin content(border padding) 控制盒模型的模式…

淘寶api接口測試方式(item_get-獲得淘寶商品詳情)

注冊淘寶開放平臺賬號&#xff1a;首先&#xff0c;你需要在淘寶開放平臺上注冊一個賬號&#xff0c;并創建一個應用。獲取App Key和Secret Key&#xff1a;在創建應用后&#xff0c;你會獲得App Key和Secret Key&#xff0c;這些憑證將用于調用API。了解淘寶商品詳情接口&…

【開源】基于Vue+SpringBoot的免稅店商城管理系統

文末獲取源碼&#xff0c;項目編號&#xff1a; S 069 。 \color{red}{文末獲取源碼&#xff0c;項目編號&#xff1a;S069。} 文末獲取源碼&#xff0c;項目編號&#xff1a;S069。 目錄 一、摘要1.1 項目介紹1.2 項目錄屏 二、系統設計2.1 功能模塊設計2.2 研究方法 三、系統…

什么是圖片懶加載(image lazy loading)?它的作用是什么?

聚沙成塔每天進步一點點 ? 專欄簡介 前端入門之旅&#xff1a;探索Web開發的奇妙世界 歡迎來到前端入門之旅&#xff01;感興趣的可以訂閱本專欄哦&#xff01;這個專欄是為那些對Web開發感興趣、剛剛踏入前端領域的朋友們量身打造的。無論你是完全的新手還是有一些基礎的開發…

如何使用vue開發vscode插件

以下是一個簡單的示例&#xff0c;演示如何使用Vue和VSCode的Webview API來開發一個簡單的VSCode插件&#xff1a; 創建一個VSCode插件項目 首先&#xff0c;你需要創建一個VSCode插件項目。你可以使用VSCode的插件生成器來快速創建一個基本的項目結構。從VSCode的命令面板中運…

【Flutter】graphic圖表實現tooltip一段時間后自動隱藏

概述 graphic圖表中提供了自定義tooltip的事件&#xff0c;可通過selections中on和clear配置手勢選項和可識別設備&#xff0c;默認情況下tooltip需要雙擊隱藏&#xff0c;但這并不符合我們的需求。通過調研發現&#xff0c;若想實現tooltip隔幾秒后隱藏&#xff0c;可通過Str…

3DMax物理畫筆物體填充放置繪制畫筆插件安裝使用方法

3DMax物理畫筆物體填充放置繪制畫筆插件&#xff0c;允許您使用筆刷以非常自然的方式用物品快速填充場景&#xff0c;并使用剛體模擬自動放置它們。 無論你是從事建筑、游戲電影還是商業。。。等等&#xff0c;你經常需要用一些物品為你的場景添加細節。手工放置它們是乏味的&…