淺談C++三種傳參方式


淺談C++三種傳參方式

C++給函數傳參中,主要有三種方式:分別是值傳遞、指針傳遞和引用傳遞。

下面通過講解和實例來說明三種方式的區別。

值傳遞

我們都知道,在函數定義括號中的參數是形參,是給函數內專用的局部變量,意味着函數接收到的是實參的副本,如果形參的值在函數內部被改變,對實參是沒有影響的

#include <iostream>

using namespace std;

void change(int formalNum) {
	formalNum = 0;
	cout << "formalNum address: " << &formalNum << endl;
}

int main() {
	int realNum = 10;
	cout << "Before Change: " << realNum << endl;
	cout << "realNum address: " << &realNum << endl;
	change(realNum);
	cout << "After Change: " << realNum ;
	return 0;
}

// 執行結果
Before Change: 10
realNum address: 008FFDA0
formalNum address: 008FFCCC
After Change: 10

可以看見,實參和形參的地址完全不一樣,而且函數完全沒有辦法改變實參的值。值傳遞的作用更多是讓函數內部了解外部參數的值。值傳遞是單向的,只能由實參傳向形參。

指針傳遞

指針傳遞很好理解,形參為指向實參地址的指針,當對形參操作時,等同於直接通過地址操作實參。

#include <iostream>

using namespace std;

void change(int *ptr) {
	*ptr = 0;
}

int main() {
	int realNum = 10;
	int* ptr = &realNum;
	cout << "Before Change: " << realNum << endl;
	change(ptr);
	cout << "After Change: " << realNum ;
	return 0;
}

// 執行結果
Before Change: 10
After Change: 0

可以很明顯地看見,我們在函數內部成功地修改了實參的值。是C++很常見的一種傳參方式。

引用傳遞

引用傳遞其實是最難理解的一種傳參方式。在詳細剖析它之前,我們先說他的功能。

向函數傳遞參數的引用調用方法,把引用的地址復制給形式參數。在函數內,該引用用於訪問調用中要用到的實際參數。這意味着,修改形式參數會影響實際參數。

那么肯定有人問了,既然都是直接影響,指針和引用有啥區別呢???那區別可大了去了。

  1. 指針從本質上是一個變量,是一個整形變量,存放的是另一個變量的地址。指針在邏輯上是獨立的,它可以被改變,甚至能改變它的值(指向其他地址),並且可以取出對應內存中的數據。
  2. 引用可以理解為外號,是另一個變量的同義詞,它在邏輯上具有依附性,所以C++也規定引用的在創立的時候就必須被初始化(現有一個變量,然后創建對該變量的引用)。而且其引用的對象在其整個生命周期中不能被改變,即自始至終只能依附於同一個變量(初始化的時候代表的是誰的別名,就一直是誰的別名,不能變)。
  3. 在引用傳遞過程中,被調函數的形式參數雖然也作為局部變量在棧中開辟了內存空間,但是這時存放的是由主調函數放進來的實參變量的地址。被調函數對形參的任何操作都被處理成間接尋址,即通過棧中存放的地址訪問主調函數中的實參變量。正因為如此,被調函數對形參做的任何操作都影響了主調函數中的實參變量。

引用的規則:

  • 引用被創建的同時必須被初始化(指針則可以在任何時候被初始化)。
  • 不能有NULL引用,引用必須與合法的存儲單元關聯(指針可以有野指針,可以指向NULL)。
  • 一旦引用被初始化,就不能改變引用的關系(指針則可以隨時改變所指的對象)。

看了這么多,指針傳遞引用傳遞的用處是什么呢?

  1. 函數內部修改參數並且希望改動影響調用函數。對比指針/引用傳遞可以將改變由形參“傳給”實參(實際上就是直接在實參的內存上修改);
  2. 當一個函數實際需要返回多個值,而只能顯式返回一個值時,可以將另外需要返回的變量以指針/引用傳遞。

下面看具體操作:

引用變量的定義方法和常規變量類似,但是其數據類型和名稱之間有一個 & 符號。例如,以下函數定義使形參 refNum 成為引用變量:

#include <iostream>

using namespace std;

void change(int& refNum) {
	refNum = 0;
	cout << "reference address: " << &refNum << endl;
}

int main() {
	int realNum = 10;
	cout << "Before Change: " << realNum << endl;
	cout << "realNum address: " << &realNum << endl;
	change(realNum);
	cout << "After Change: " << realNum ;
	return 0;
}

// 執行結果
Before Change: 10
realNum address: 00A4F9F4
reference address: 00A4F9F4
After Change: 0

可以看見,引用傳遞成功地改變了參數的值,同時形參的地址和實參的地址其實是一模一樣的

在學完數據結構和算法后,我對其又有新的認識。

void func(nodeList* &Node){
    // 這里對Node進行了操作
}

上面這個傳參,又有*又有&,第一眼有點懵,后來細想一下其實很簡單。

nodeList是一個整體,代表傳進來的是nodeList這個類的指針。我們之前已經學到了,指針其實是一個變量,它的基本性質和變量沒有區別。那么我們要在函數體內改變其值,最安全的辦法就是傳入其引用(也可以創建指針的指針)。所以這里的&Node表示引用Node的實參,是Node的別名,操作引用變量就相當於操作實參變量。*


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM