日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

c++ 函数的值传递,引用传递 和 引用返回的探索

發布時間:2023/12/10 c/c++ 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c++ 函数的值传递,引用传递 和 引用返回的探索 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2019獨角獸企業重金招聘Python工程師標準>>>

前言

C++的函數參數和返回分為按值傳遞和按引用傳遞,應用到類上面,會涉及到類的 賦值操作 復制函數 構造函數 析構函數

雖然java開發了兩年,但對我而言c++我還只是一個初學者.c++還有很多陌生的特性需要自己親自探索.這里用實際例子作為探索,不對之處望斧正:

由于基本類型和類在函數里的生命周期是相似的,這里以一個自定義類為例,一是為了方便觀察對象的地址,二是可以了解每一步會涉及到類的哪些生命周期:

類的定義

#include <iostream>using std::cout; using std::endl; using std::string;class A { public:A() {cout << "構造函數:" << this << endl;}A(const A &input) {cout << "復制函數:" << this << endl;}// 復制直接返回 *this 本身A &operator=(const A &input) {cout << "賦值函數:" << this << endl;// this 其實是個新的內存空間,啥值都沒設置return *this;}~A() {cout << "析構函數:" << this << endl;} };

值傳遞 和 返回值

我們定義一個值傳遞的函數,返回的也是值

A test1(A a) {cout << "test1函數體:&a=" << &a << endl;return a; }

執行main函數如下

int main() {cout << "--- 對象創建 ---" << endl;A a;cout << "--- 函數調用 ---" << endl;A b = test1(a);cout << "--- 結束 ---" << endl;return 0; }

執行結果

--- 對象創建 --- 構造函數:0x7fff5ed19768 --- 函數調用 --- 復制函數:0x7fff5ed19750 test1函數體:&a=0x7fff5ed19750 復制函數:0x7fff5ed19758 析構函數:0x7fff5ed19750 --- 結束 --- 析構函數:0x7fff5ed19758 析構函數:0x7fff5ed19768

由此可見,在函數的棧幀里,對入參a進行了一次復制(0x7fff5ed19750),而在返回棧幀里的input時,又會對函數結果復制生成一個臨時變量(0x7fff5ed19758),并回收棧幀里的input. 函數結束會把臨時變量返回給b,至此結束函數調用.也就是說,這里函數的入參和返回各涉及一次復制操作

函數入參和返回使用引用

我們對test1做出修改,將入參和返回變更為引用,如下

A &test1(A &a) {cout << "test1函數體:&a=" << &a << endl;return a; }

將main中的b也變更為引用如下:

int main() {cout << "--- 對象創建 ---" << endl;A a;cout << "--- 函數調用 ---" << endl;A &b = test1(a);cout << "--- 結束 ---" << endl;return 0; }

執行結果:

--- 對象創建 --- 構造函數:0x7fff56dd5768 --- 函數調用 --- test1函數體:&a=0x7fff56dd5768 --- 結束 --- 析構函數:0x7fff56dd5768

因為是引用函數棧幀內并沒有進行任何復制操作

函數返回的臨時變量探索

如果函數不返回引用,或b不是引用,仍然會產生臨時變量

A test1(A &a) {cout << "test1函數體:&a=" << &a << endl;return a; } A& test2(A &a) {cout << "test2函數體:&a=" << &a << endl;return a; } int main() {cout << "--- 對象創建 ---" << endl;A a;cout << "--- 函數調用1 ---" << endl;A b1 = test1(a);cout << "--- 函數調用2 ---" << endl;A b2 = test2(a);cout << "--- 結束 ---" << endl;return 0; }

返回結果如下

--- 對象創建 --- 構造函數:0x7fff5daae758 --- 函數調用1 --- test1函數體:&a=0x7fff5daae758 復制函數:0x7fff5daae748 --- 函數調用2 --- test2函數體:&a=0x7fff5daae758 復制函數:0x7fff5daae740 --- 結束 --- 析構函數:0x7fff5daae740 析構函數:0x7fff5daae748 析構函數:0x7fff5daae758

test1和test2的區別只在于返回結果是否為引用,但在棧幀外都產生了臨時變量

賦值操作探索

這里再對賦值做探索,這次把以上3中情況合在一起為例,如下

A &test1(A &a) {cout << "test1函數體:&a=" << &a << endl;return a; } A &test2(A a) {cout << "test2函數體:&a=" << &a << endl;return a; } A test3(A a) {cout << "test2函數體:&a=" << &a << endl;return a; } int main() {cout << "--- 對象創建 ---" << endl;A a;cout << "--- 函數調用1 ---" << endl;a = test1(a);cout << "--- 函數調用2 ---" << endl;a = test2(a);cout << "--- 函數調用3 ---" << endl;a = test3(a);cout << "--- 結束 ---" << endl;return 0; }

輸出結果

--- 對象創建 --- 構造函數:0x7fff513b6748 --- 函數調用1 --- test1函數體:&a=0x7fff513b6748 賦值函數:0x7fff513b6748 --- 函數調用2 --- 復制函數:0x7fff513b6738 test2函數體:&a=0x7fff513b6738 賦值函數:0x7fff513b6748 析構函數:0x7fff513b6738 --- 函數調用3 --- 復制函數:0x7fff513b6728 test2函數體:&a=0x7fff513b6728 復制函數:0x7fff513b6730 賦值函數:0x7fff513b6748 析構函數:0x7fff513b6730 析構函數:0x7fff513b6728 --- 結束 --- 析構函數:0x7fff513b6748
  • test1 相當于a=a;除了將值賦值給自己外棧幀沒有額外操作,這個很好理解
  • test2 對入參進行復制,并把復制的入參值賦值給a并在函數棧幀結束后回收入參
  • test3 比較復雜,會復制入參和臨時變量,并把臨時變量賦值給a,賦值結束后對入參和臨時變量進行回收

轉載于:https://my.oschina.net/tdONEmadao/blog/915677

總結

以上是生活随笔為你收集整理的c++ 函数的值传递,引用传递 和 引用返回的探索的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。