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

C++中的函數返回值與拷貝用法

 更新時間:2022年11月25日 09:25:16   作者:白給程序猿  
這篇文章主要介紹了C++中的函數返回值與拷貝用法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

C++函數返回值與拷貝

先來談談對C++中函數返回return的理解,自己本來在學Java,但是平時學校的項目是用的C++,所以在平時搬磚時經常會有一些問題,今天就來談談前段時間注意到的一個很小的知識點,話不多說,先上列子。

首先我們創(chuàng)建一個簡單的Man類,實現(xiàn)它的無參構造函數、有參構造函數和析構函數:

class Man
{
public:
	Man() {
		cout << "構造" << endl;
		data = new int(0); }

	Man(const Man& m)
	{
		cout << "拷貝構造" << endl;
		this->data = m.data;
	}
	
	~Man() 
	{ 
		cout << "析構" << endl;
		delete data; 
	}
	
	int* data;
};

聲明一個get函數獲取一個Man的對象

Man get(Man& m)
{
	cout << "----" << endl;
	return m;
}

main函數中執(zhí)行下列代碼

 void main()
{
		Man m, n;
		//cout << "before m=" << &m << "n=" << &n << endl;
		*m.data = 5;
		printf("m.data is %d\n", *m.data);
		n = get(m); 

		printf("m.data is %d\n", *m.data);
		printf("n.data is %d\n", *n.data);
	
	    system("pause");
	    }

你可以試著想一想三個printf的輸出結果分別是多少

執(zhí)行結果如下圖所示:

在輸出結果里我們可以清楚的看到,Man m, n; 創(chuàng)建了m,n兩個對象,調用了構造函數,對m對象中的data賦值,然后我們調用get(Man& man) 函數,注意這里函數參數是引用類型,因此傳入的對象是m對象本身,這里我們要區(qū)別get(Man man) 兩種函數參數類型的區(qū)別,我稍后再提。get(Man& man) 函數調用完畢后,返回對象m。

按照我們過去的分析會認為對象n等于get函數返回的m對象 (n=m) (注意這里等號=被重載過),m對象中的int* data 成員值直接賦值給了n對象中的data成員,輸出時照理說m和n的data值都應該等于5的,但是:

為什么這里輸出結果卻表明這個data指針指向的空間被銷毀了?

為什么get函數執(zhí)行里會多出了拷貝構造和析構這兩個過程呢?

如果我們返回值為Man&會有什么區(qū)別變化呢?

這里我們做一個對比,填加一個getR函數,返回值為Man& 引用類型:

Man& getR(Man& m)
{?
? ? cout << "----" << endl;
?? ?return m;
}

接下來我們調用getR這個函數看一看輸出結果:

void main()
{
?? ??? ?Man m, n;
?? ??? ?*m.data = 5;
?? ??? ?printf("m.data is %d\n", *m.data);
?? ??? ?n = getR(m);
?? ??? ?
?? ??? ?printf("m.data is %d\n", *m.data);
?? ??? ?printf("n.data is %d\n", *n.data);
?? ??? ?
?? ? ? ?system("pause");
?? ? ? ?}

執(zhí)行結果如下圖所示: 

執(zhí)行結果如下圖所示:

可以看到,當我們返回的是m對象的的引用時,getR 函數執(zhí)行時沒有調用拷貝構造和析構函數

這里我解釋一下返回值不是引用的情況時整個函數執(zhí)行的過程

(個人拙劣的理解)

我們再回到get這個函數:

Man get(Man& m)
{
	cout << "----" << endl;
	return m;
}

首先函數參數傳入m這個對象的引用我們毋庸置疑,關鍵就在return這里。

我們捋一捋函數從開始到結束這個過程,隨著Main函數調用get函數,get函數入棧,同時get方法對應的棧幀(儲存函數局部變量、返回地址等信息)也入棧,這里的局部變量也就是m對象的引用。

當我們return這個m對象時,會在內存中創(chuàng)建一個臨時的Man temp對象,同時這個temp對象調用其拷貝構造函數,也就是Man temp(m) 。

完成temp對象的創(chuàng)建后,get函數出棧,對應的棧區(qū)內容被銷毀,這時系統(tǒng)會調用m對象的析構函數,注意這里有一個陷阱?。。?!

由于m對象是在main方法下的棧區(qū)創(chuàng)建的,因此get方法出棧后,系統(tǒng)調用m析構函數并沒有真正把m對象在棧區(qū)銷毀(因為它根本就不是在get方法的棧區(qū)上),調用析構函數僅僅是將data指針所指向的內存空間被銷毀了(delete data;),這也解釋了為什么m.data的值為-572662307。

main方法執(zhí)行完畢后,m對象才會調用析構函數真正被銷毀,當然,這也會帶來另一個問題,data指向的內存區(qū)被執(zhí)行了兩次delete,運行結束后你也就會發(fā)現(xiàn)還會有一個**“析構”**和一個內存問題報錯。

回到我們返回的值上:

n = get(m); 

這里實際上可以理解成

Man temp(m);
n=temp;

當然由于get函數的退出調用析構函數時,data指針指向的內存區(qū)域數據已經被銷毀,自然n和m得到的值是一個錯誤值了。

總結

對于函數返回值類型為非引用類型(當然引用類型也可以理解為Man& temp=m),都是會在內存中創(chuàng)建一個臨時變量,將返回值拷貝到臨時變量中,而返回值是作為函數調用棧區(qū)中的局部變量,隨著函數的返回,棧區(qū)的銷毀,而被銷毀。

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • C++數據模型應用在QML委托代理機制中

    C++數據模型應用在QML委托代理機制中

    這篇文章主要介紹了在QML委托代理機制中使用C++數據模型,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-08-08
  • 使用VSCode和VS2017編譯調試STM32程序的實現(xiàn)

    使用VSCode和VS2017編譯調試STM32程序的實現(xiàn)

    這篇文章主要介紹了使用VSCode和VS2017編譯調試STM32程序的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-05-05
  • C語言算法積累分離數位示例

    C語言算法積累分離數位示例

    這篇文章主要為大家介紹了C語言算法積累分離數位的實現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06
  • C語言對冒泡排序進行升級介紹

    C語言對冒泡排序進行升級介紹

    大家好,本篇文章主要講的是C語言對冒泡排序進行升級介紹,感興趣的同學趕快來看一看吧,對你有幫助的話記得收藏一下
    2022-01-01
  • Qt圖形圖像開發(fā)之曲線圖表庫QChart編譯安裝詳細方法與使用實例

    Qt圖形圖像開發(fā)之曲線圖表庫QChart編譯安裝詳細方法與使用實例

    這篇文章主要介紹了Qt圖形圖像開發(fā)之曲線圖表庫QChart編譯安裝詳細方法與使用實例,需要的朋友可以參考下
    2020-03-03
  • 詳解C++中的菱形繼承問題

    詳解C++中的菱形繼承問題

    這篇文章主要介紹了詳解C++中的菱形繼承問題,在多繼承結構中,存在著很多問題,比如從不同基類中繼承了同名成員,派生類中也定義了同名成員,這種二義性問題很好解決,加上要訪問的基類的類名限制就可以了,需要的朋友可以參考下
    2023-08-08
  • 淺談C++類型轉化(運算符重載函數)和基本運算符重載(自增自減)

    淺談C++類型轉化(運算符重載函數)和基本運算符重載(自增自減)

    下面小編就為大家?guī)硪黄獪\談C++類型轉化(運算符重載函數)和基本運算符重載(自增自減)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06
  • 嵌入式項目使用C語言結構體位段特性實現(xiàn)斷言宏校驗數據范圍有效性的方法

    嵌入式項目使用C語言結構體位段特性實現(xiàn)斷言宏校驗數據范圍有效性的方法

    今天小編就為大家分享一篇關于嵌入式項目使用C語言結構體位段特性實現(xiàn)斷言宏校驗數據范圍有效性的方法,小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • QT5中使用QRegularExpression代替QRegExp方法代碼

    QT5中使用QRegularExpression代替QRegExp方法代碼

    這篇文章主要給大家介紹了關于QT5中使用QRegularExpression代替QRegExp的相關資料,正則表達式(regep)是處理字符串和文本的強大工具,驗證regexp可以測試子字符串是否滿足某些條件,例如是整數或不包含空格,需要的朋友可以參考下
    2024-04-04
  • Opencv二幀差法檢測運動目標與提取輪廓

    Opencv二幀差法檢測運動目標與提取輪廓

    這篇文章主要為大家詳細介紹了Opencv使用二幀差法檢測運動目標與提取輪廓,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-03-03

最新評論

祁阳县| 资中县| 乳山市| 德清县| 马边| 建平县| 宁晋县| 德清县| 高清| 新疆| 南丰县| 定南县| 石城县| 峨边| 舟曲县| 稻城县| 霞浦县| 麻阳| 兴文县| 长葛市| 四平市| 昭苏县| 湄潭县| 正安县| 晋州市| 光山县| 乳源| 亳州市| 伽师县| 齐齐哈尔市| 合山市| 紫阳县| 专栏| 浮山县| 珲春市| 洛川县| 依兰县| 宜章县| 贡觉县| 安康市| 江北区|