1. 程式人生 > >C++ 基礎之 "引用形參" 和 "利用const引用避免複製" &

C++ 基礎之 "引用形參" 和 "利用const引用避免複製" &

之前兩篇文章裡的兩個函式如下所示:

//過載操作符+  
    Vector3 operator+(const Vector3 &a){  
        return Vector3(x + a.x,y + a.y,z+a.z);  
    }
//比較兩個數,如果相同返回0,如果v1大,返回1,如果v2大,返回-1  
int compare(const int &v1, const int &v2)  
{  
    if(v1 < v2) return -1;  
    if(v2 < v1) return 1;  
    return 0;  
} 

因為之前是用C#和Java比較多,就是無法理解這兩個函式的引數定義,為什麼要加上const和&。其實有時候看到&,*,T等符號就會頭大。如果在java中第二個函式我肯定就會這樣寫:

//比較兩個數,如果相同返回0,如果v1大,返回1,如果v2大,返回-1  
int compare( int v1,  int v2)  
{  
    if(v1 < v2) return -1;  
    if(v2 < v1) return 1;  
    return 0;  
} 

先不管上面的東西,再來看一個出現無數次的交換例子:
//把形參定義為引用型別
void swapOne(int& a, int& b)
{
    int tmp = b;
	b = a;
	a = tmp;
}
//使用複製實參,只是改變區域性副本,而傳遞函式的實參沒有修改
void swapTwo(int a,int b)
{
    int tmp = b;
	b = a;
	a = tmp;
}

int main(int argc, char* argv[])
{
	int a = 1, b = 2;
	printf("before swap,a:%d,b:%d\n",a,b);
	swapOne(a,b);
	printf("after swap,a:%d,b:%d\n",a,b);


	printf("before swap,a:%d,b:%d\n",a,b);
	swapTwo(a,b);
	printf("after swap,a:%d,b:%d\n",a,b);
	return 0;
}

結果如下:

從結果看出,swapOne函式使用引用形參成功交換了a,b變數。而swapTwo函式沒有交換成功。

swapTwo使用的是普通的非引用型別的引數,是通過複製對應的實參實現初始化,傳遞函式的實參沒有改變。

而swapOne中,引用形參直接關聯到其繫結的物件,而並非這些物件的副本。所以交換會成功。

//比較兩個數,如果相同返回0,如果v1大,返回1,如果v2大,返回-1  
int compare(const int &v1, const int &v2)  
{  
    if(v1 < v2) return -1;  
    if(v2 < v1) return 1;  
    return 0;  
} 

上面這例子中的const還有什麼作用呢?原來使用const可以避免引用複製,提高效能,swapOne中當然不能使用了,因為它要改變值,而compare函式只是比較兩個數的大小,沒有交換,所以加上const可以提高效能。因為複製物件需要付出時間和儲存空間代價。

後記:最近無意中看到了《Effective C++》的條款20“寧以pass-by-reference-to-const 替換 pass-by-value”。中也談到了這個問題。

class Person{
public:
	Person();
	virtual ~Person();
	...
private:
	std::string name;
	std::string address;
};

class Student:public Person{
public:
	Student();
	~Student();
	...
private:
	std::string schoolName;
	std::string schoolAddress;
}

假設現在有這樣一個函式

bool validateStudent(Student s);

如果用by Value方式來呼叫就是

Student plato;

bool platoIsOk = validateStudent(plato);

因為Student類是繼承Person類,每個類都有兩個string。書上說,by value方式傳遞一個Student物件,總體成本是"六次建構函式和六次解構函式"!

如果改成成pass by reference-to-const:

bool validateStudent(const Student& s);沒有任何建構函式或解構函式被呼叫,因為沒有任何新物件被建立。

相關推薦

C++ 基礎 "引用" "利用const引用避免複製" &

之前兩篇文章裡的兩個函式如下所示: //過載操作符+ Vector3 operator+(const Vector3 &a){ return Vector3(x + a.x,y + a.y,z+a.z); } //比較兩

C++函式引用引用

C++函式引用形參和非引用形參 C++中函式的形參主要有兩種型別: 非引用形參和引用形參, 對應兩種不同的引數傳遞方式。 void f(int t); void f(int &t); 非引用行參是實參的一個副本, 故對非引用形參的修改不會影響實參; 引用形參是實參的別名,

C++ 引用指標

從引用形參和非引用形參的區別來看,似乎任何時候使用引用形參都指標好, 既少了實參到形參拷貝的開消,也同樣可以操作(非const )實參。 那指標形參有沒有什麼優點呢? 1. 指標形參比引用形參更能清晰的向函式呼叫者表明函式可能會修改實引數 void f1(int *

C++中一般引用引用的問題

#include<iostream> using namespace std; int f(const int &a){return a;} int g(int &a){return a;} int h(int a){return a;} int ma

C#基礎數(二) 數組數、可選數與命名

編譯器 line 示例 報錯 一個 傳遞 for 介紹 public   這次介紹的三個參數皆屬於語法糖。   4.數組參數    聲明方法時,在形參前加params關鍵字。簡化了參數調用,增加了可讀性。   用法:   (1)在參數為數組時使用   (2)每個方法只能有一

c++入門再話記憶體引用

此處沒有程式碼,僅僅討論一些這樣的問題:我們為何使用引用?在哪裡使用引用? 首先從函式的角度思考?:函式進行一般引數傳遞的時候,是怎麼樣傳遞的?普通型別的引數傳遞,是將傳遞的實參複製一份,到另一個記憶體空間,這其中包含了int,char ,甚至struct。那麼從記憶體的角度講:如果我們傳遞的引數非常佔用記

C語言函式篇(二)

參引數:形參和實參 ------------------------------- 形參實現一種資料傳入的介面 ,由實參 拷貝 給 形參 拷貝!!!!!!!!!!! 拷貝1: void func(int tmp

C++中的const限定符(5)——const

1、當形參有頂層const時,傳給它常量物件或非常量物件都是可以的,這一點複合之前所說的,因為形參的初始值是拷貝了實參的。 2、在定義過載函式時,需要注意:對於形參是否是const的,是無法被編譯器所區分的。 void foo(int i){} void foo(co

java基礎----基本資料型別引用資料型別的引數傳遞過程(一)

值傳遞:方法呼叫時,實際引數把它的值傳遞給對應的形式引數,方法執行中形式引數值的改變不影響實際引數的值。 引用傳遞:也稱為傳地址。方法呼叫時,實際引數的引用(地址,而不是引數的值)被傳遞給方法中相對應的形式引數,在方法執行中,對形式引數的操作實際上就是對實際引

C--關於函式返回值的思考

關於函式形參和返回值的思考 前提 在呼叫Linux系統中的時間API介面時,仔細想想如何傳參以及接收返回值,寫程式碼執行的時候還是遇到了點問題,現在想通了好好梳理一番。Linux終端中使用man 2 time和man 3 ctime查詢後,可以得到很多相關內容,

C語言第55課初始

·第55課初始形參和實參 ·例子:自定義冪函式 #include<stdlib.h> //自行實現pow函式 //求第一個引數的n次冪 double power(double,int);//函式原型

什麼時候應使用指標?什麼時候就使用引用?解釋兩者的優點缺點。

1.當函式需要處理陣列且函式體不依賴於陣列的長度時應使用指標形參,其他情況下應使用引用形參: 2.指標形參的優點:可以明確地表示函式所操縱的是指向資料元素的指標,而不是陣列本身,而且可以使用任意長度的實引數組來呼叫函式;         缺點:函式體不能依賴於陣列的長度,

指標傳遞指向指標的引用

1.指標形參:實現指標指向的值的交換(指標本身不變) 函式的形參是指標時,將複製實參指標,形參的任何改變僅作用於實參的區域性副本,如果函式將新指標賦給形參,主調函式使用的實參指標本事的值沒有變化。 程

C++基礎八】函式指標回撥函式

C++很多類庫都喜歡用回撥函式,MFC中的定時器,訊息機制,hook機制等待,包括現在在研究的cocos2d-x中也有很多的回撥函式。1.回撥函式什麼是回撥函式呢?回撥函式其實就是一個通過函式指標呼叫的函式!假如你把A函式的指標當作引數傳給B函式,然後在B函式中通過A函式傳進

C++Primer:函式(引數傳遞:引用

1.問題的引入 考慮下面不適宜複製實參的例子,該函式希望交換兩個實參的值: <span style="font-size:18px;">void swap(int v1, int v2

C++函式——const

    頂層const: 表示任意的物件是常量。      底層const: 與指標和引用等複合型別有關。     對指標而言, 頂層const表示指標本身是個常量, 而底層const表示指標所指的物件是一個常量。 int i = 22; const

c語言中的區別?

形式引數和實際引數 函式的引數分為形參和實參兩種。在本小節中,進一步介紹形參、實參的特點和兩者的關係。形參出現在函式定義中,在整個函式體內都可以使用,離開該函式則不能使用。實參出現在主調函式中,進入被調函式後,實參變數也不能使用。形參和實參的功能是作資料傳送。發生函式呼叫

C++拷貝建構函式_為什麼只能是引用(不能傳值或指標)

先給出答案: 拷貝建構函式不能用數值或指標形參原因,不是為了節省建立副本的空間與時間。而是那樣做會無限迴圈遞迴下去。 舉個例子來看一下為什麼會這樣。(反例) class Example() { public: Example(int a):aa(a) {}

Java中的的區別以及傳值呼叫引用呼叫

原文地址:http://blog.csdn.net/miniminiyu/article/details/52061401  名詞解析: 1.形參:用來接收呼叫該方法時傳遞的引數。只有在被呼叫的時候才分配記憶體空間,一旦呼叫結束,就釋放記憶體空間。因此僅僅在方法內有效

值型別引用型別,,傳值引用

    C# 中有兩種型別:引用型別和值型別。引用型別的變數儲存對其資料(物件)的引用(地址),而值型別的變數直接包含其資料(副本)。     對於引用型別,兩種變數可引用同一物件;因此,