程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++ 基礎之 "引用形參" 和 "利用const引用避免復制&a

C++ 基礎之 "引用形參" 和 "利用const引用避免復制&a

編輯:C++入門知識

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

[cpp] 
//重載操作符+   
    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中第二個函數我肯定就會這樣寫:
[java]
//比較兩個數,如果相同返回0,如果v1大,返回1,如果v2大,返回-1   
int compare( int v1,  int v2)   
{   
    if(v1 < v2) return -1;   
    if(v2 < v1) return 1;   
    return 0;   
}  

先不管上面的東西,再來看一個出現無數次的交換例子:
[cpp] 
//把形參定義為引用類型 
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中,引用形參直接關聯到其綁定的對象,而並非這些對象的副本。所以交換會成功。
[cpp] 
//比較兩個數,如果相同返回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”。中也談到了這個問題。
[cpp] 
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);沒有任何構造函數或析構函數被調用,因為沒有任何新對象被創建。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved