欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++中的函數(shù)返回值與拷貝用法

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

C++函數(shù)返回值與拷貝

先來談?wù)剬++中函數(shù)返回return的理解,自己本來在學(xué)Java,但是平時學(xué)校的項目是用的C++,所以在平時搬磚時經(jīng)常會有一些問題,今天就來談?wù)勄岸螘r間注意到的一個很小的知識點,話不多說,先上列子。

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

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

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

聲明一個get函數(shù)獲取一個Man的對象

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

main函數(shù)中執(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的輸出結(jié)果分別是多少

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

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

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

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

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

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

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

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

接下來我們調(diào)用getR這個函數(shù)看一看輸出結(jié)果:

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í)行結(jié)果如下圖所示: 

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

可以看到,當(dāng)我們返回的是m對象的的引用時,getR 函數(shù)執(zhí)行時沒有調(diào)用拷貝構(gòu)造和析構(gòu)函數(shù)

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

(個人拙劣的理解)

我們再回到get這個函數(shù):

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

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

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

當(dāng)我們return這個m對象時,會在內(nèi)存中創(chuàng)建一個臨時的Man temp對象,同時這個temp對象調(diào)用其拷貝構(gòu)造函數(shù),也就是Man temp(m) 。

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

由于m對象是在main方法下的棧區(qū)創(chuàng)建的,因此get方法出棧后,系統(tǒng)調(diào)用m析構(gòu)函數(shù)并沒有真正把m對象在棧區(qū)銷毀(因為它根本就不是在get方法的棧區(qū)上),調(diào)用析構(gòu)函數(shù)僅僅是將data指針?biāo)赶虻膬?nèi)存空間被銷毀了(delete data;),這也解釋了為什么m.data的值為-572662307。

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

回到我們返回的值上:

n = get(m); 

這里實際上可以理解成

Man temp(m);
n=temp;

當(dāng)然由于get函數(shù)的退出調(diào)用析構(gòu)函數(shù)時,data指針指向的內(nèi)存區(qū)域數(shù)據(jù)已經(jīng)被銷毀,自然n和m得到的值是一個錯誤值了。

總結(jié)

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

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

相關(guān)文章

  • 深入解析C語言中typedef的四個用途

    深入解析C語言中typedef的四個用途

    以下是對C語言中typedef的四個用途進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過來參考下
    2013-08-08
  • C++中四種加密算法之DES源代碼

    C++中四種加密算法之DES源代碼

    本篇文章主要介紹了C++中四種加密算法之DES源代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。
    2016-11-11
  • C++如何計算結(jié)構(gòu)體與對象的大小

    C++如何計算結(jié)構(gòu)體與對象的大小

    這篇文章主要給大家介紹了關(guān)于C++如何計算結(jié)構(gòu)體與對象大小的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • C++STL教程之vector模板的使用

    C++STL教程之vector模板的使用

    模板類vector是一個動態(tài)數(shù)組,類似于string類,可存放任意類型,能夠末尾、中間增加數(shù)據(jù),基本上是是new創(chuàng)建動態(tài)數(shù)組的替代品,vector可以自動完成new和delete
    2022-08-08
  • C/C++中虛函數(shù)詳解及其作用介紹

    C/C++中虛函數(shù)詳解及其作用介紹

    這篇文章主要介紹了C/C++中虛函數(shù)詳解及其作用介紹,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-09-09
  • linux c語言操作數(shù)據(jù)庫(連接sqlite數(shù)據(jù)庫)

    linux c語言操作數(shù)據(jù)庫(連接sqlite數(shù)據(jù)庫)

    linux下c語言操作sqlite數(shù)據(jù)庫實例方法,大家參考使用吧
    2013-12-12
  • C++構(gòu)造函數(shù)拋出異常需要注意的地方

    C++構(gòu)造函數(shù)拋出異常需要注意的地方

    這篇文章主要介紹了C++構(gòu)造函數(shù)拋出異常需要注意的地方,幫助大家更好的理解和學(xué)習(xí)c++,感興趣的朋友可以了解下
    2020-08-08
  • c文件匯編后函數(shù)參數(shù)傳遞的不同之處

    c文件匯編后函數(shù)參數(shù)傳遞的不同之處

    在w7 32位系統(tǒng)下把c文件匯編后,確實與mac后的差異很大。可不僅僅是寄存器eax與rax的區(qū)別。我想說的是函數(shù)參數(shù)傳遞的不同
    2013-11-11
  • Qt學(xué)習(xí)之QListWidget控件的使用教程詳解

    Qt學(xué)習(xí)之QListWidget控件的使用教程詳解

    這篇文章主要為大家詳細(xì)介紹了Qt中QListWidget控件的使用教程,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)Qt有一定的幫助,需要的可以參考一下
    2022-12-12
  • 利用c++寫一個簡單的推箱子小游戲

    利用c++寫一個簡單的推箱子小游戲

    推箱子想必是很多人童年時期的經(jīng)典游戲,我們依舊能記得抱個老人機(jī)娛樂的場景,下面這篇文章主要給大家介紹了關(guān)于如何利用c++寫一個簡單的推箱子小游戲的相關(guān)資料,需要的朋友可以參考下
    2021-09-09

最新評論