引數預設,引用

2021-07-14 05:59:01 字數 4229 閱讀 6753

本篇文章將整理出關於引數預設和引用的一些知識。

(一)引數預設:

引數預設包括全預設和半預設。顧名思義,全預設就是函式的所有引數都給出預設值,半

預設就是僅有函式的部分引數給出了預設值。

看下邊的一段**:

#includeusing namespace std;

int add(int x, int y)

int main()

要是寫出上邊的一段**,低版本的vs會編譯不通過,報錯是add函式不

接收0個引數,

高版本vs會有紅色標註。要是對於函式呼叫的時候不想給出引數,我們可以使用預設參

數,若將add函式寫成這樣就好了:

int add(int x = 0, int y = 0)

這就是所謂的全預設。那麼半預設呢??繼續例項:

int add(int x , int y = 0)

int main()

這樣子的話,最後會得到10和0相加。當然呼叫的時候,我們也可以給出兩個引數。如果

我們將x給出缺省,y不預設,看可以不??

int add(int x = 0 , int y)

要是add函式寫成上邊這樣,高版本vs編譯器會紅線報錯:預設引數不在引數列表末尾。

想想這是為什麼?其實,想一下就明白了,呼叫的時候(當然實參是只有乙個)會把給

出的實參賦值給函式引數列表的第乙個形參,肯定就不對了嘛。要是用更專業的說法解

釋,本人認為:

函式引數入棧的時候是實參進入add

函式的棧幀,直接就當作第乙個引數,所以~

總結:使用半預設,預設的引數只能在引數列表的最後邊。

預設引數的用途:假如要傳性別這個引數給函式,我們又約定預設為男,所以,只需要

在需要傳的性別是女時,給出引數。這就是預設引數的用途。

(二)引用

引用就是給乙個變數起乙個別名。

比如:

int a = 10;

int &ra = a;//ra是a的別名

int &refa = a;//refa也是a的別名

總結:乙個變數可以有多個別名。

定義引用的時候必須初始化(指明定義的引用是哪個變數的別名)。

引用只能在初始化的時候引用一次。

既然說,乙個變數可以有多個別名,改變了別名的值,也就改變了變數的值,是不是感

覺引用就很不安全了??

其實並不是,如果不想改變,可以使用const修飾。

int a= 10;

const int &ra = a;

ra = 20;//報錯!

關於const,在c中const修飾的變數是常變數,既有常量的屬性,也有變數的屬性。在c

++中,const修飾的變數就是常量。不可修改。

在學習指標的時候,如果乙個函式的功能僅僅是列印或者是某個引數不可以被改變的時

候,我們可以用const修飾。在使用引用的時候也是一樣的。

舉例:

void print_a(const int &ra)

int main()

在cpp中,如果const修飾的是區域性變數,則該區域性變數是在棧裡。不是不可以修改,可

以使用指標修改。

如果const修飾的是全域性變數,不使用的時候是不會被分配空間的(&n是錯誤的),只有

在使用的時候也是有位址的。

const int n = 10;

int main()

;//這裡並不算使用n,此時的n仍相當於巨集識別符號

const int *p = &n;//n才有空間,並且是唯讀區,不可修改的。

system("pause");

return 0;

}

關於const引用的正確使用:看下邊的幾段**:

const int n = 10;

int &refn = a;

此時 refa是可以改變的,進而n的值可以改變。這就不對了嘛。(n是不可以改變的)。

使得n從安全變成不安全。

int m = 10;

const int &refm = m;

這個就是正確的。使得m從不安全變得安全。

const int &refd= 5;
這個是正確的。const修飾的refd是乙個常量的引用。

double d = 6.15;

int &refd = d;

這個是不對的。要是這樣就對了:

double d = 6.15;

const int &refd = d;

為什麼呢??由於引用的型別是int,變數的型別是double,所以此時就會用double型別

的d建立乙個臨時變數(也是d的隱式型別轉換),refd引用的是臨時變數。確切的說就

是臨時常量。此時refd =6

refd和d不在乙個空間。

引用作為函式引數:

這裡需要宣告:引用的底層仍然是指標(這個可以通過彙編**觀到)。 

下邊我們來測試傳引用和傳值得效率問題:

#include#includeusing namespace std;

struct bigdata

;int getdata(bigdata bd)

int main()

; int i = 0;

int start = gettickcount();

for (i = 0;i < 100000000;i++)

int end = gettickcount();

cout << end - start << endl;

system("pause");

return 0;

}

**測試出的結果是6000毫秒左右。注意:每次執行的結果都不大一樣,這根cpu的狀態

有關。當把上邊**改為傳引用:效率可以提高大約一半,自己可以嘗試。

引用作為函式的返回值:

看**:

int& fun()

int main()

上邊這段**確實可以輸出10.不過要是把上邊的**做以修改:

int& fun()

int main()

看上邊的**,在高版本的vs下輸出:

楊先生你好10

在低版本環境下ret的值會被改變。因為ret接收的是區域性變數num,兩者占用同乙個空間

當num消失了,ret也就消失了,變成隨機值。

高版本vs(比如vs2015)為什麼ret的值一直是10,不知道做了什麼優化。。

如果將上邊的**做以修改:

int& fun()

int main()

這個ret的值不會改變。看原理:

後者的ret就不是引用了,儲存的僅僅是num的值,所以不會隨著num的消失而消失。

當引用作為函式的返回值的時候,有時會提高效率,有時並不會~~

我們知道,當函式的返回值,int或者double等等內建型別時,返回值是用暫存器帶回

的。然而最大的暫存器也就32位,要是我們要返回乙個比較大的結構體時,會使用引用

,引用不會建立臨時變數,直接把需要帶回的值賦值給接收返回值的變數。

總結:用函式的返回值的型別不是內建型別時,使用引用返回,會提高效率(減少創

建臨時物件)。

當返回的是內建型別時,會用暫存器帶回,跟使用引用返回的效率差不多。

引用和指標的區別:

1.指標在定義的時候可以不初始化,但是引用不行。

2.引用只能引用乙個變數,而一般的指標變數並不是(除了const修飾的指標)

3.指標的大小僅與品台有關,而引用的大小與引用的物件的型別有關。

4.指標自加時,使得指標指向當前指向空間的下乙個空間;引用自加時,會使自身和它

所引用的物件的值加1.

5.引用比指標更安全。(使用指標時,一定要檢查指標的值是否是null)

越努力,越幸運~~

03 bool,const,引用,預設引數

一 bool bool val true vs中佔1位元組,記憶體中數值為0x01 val false 記憶體中數值為0x00 val 100 記憶體中數值為0x01,warning c4305 從 int 到 bool 截斷 val 1 記憶體中數值為0x01,warning c4305 從 in...

C 中的預設引數 引用 函式過載

我們學過c語言的都知道,在函式沒有指定指定引數列表時,預設可以接受任意多個引數,便有了可變引數列表。在c 中,對於引數列表有了嚴格的檢測,對於沒有引數列表的函式,預設為void,不允許接受任何引數。那麼預設引數又是什麼呢?下面我們通過乙個例子來說明。include using namespace s...

python 預設引數 Python預設引數有坑?

最近有小夥伴在面試中遇到了 關於函式預設引數的坑 的題目,少數夥伴對此問題理得不是太清楚,今天匯智妹請到匯智動力高階教師鄧老師為大家詳細講解一下,幫助不太清楚的小夥伴清晰的梳理一遍。鄧老師本次主要從以下三點來講解 什麼是預設引數?函式預設引數的坑是什麼?函式預設引數為什麼會有坑?一 什麼是預設引數 ...