差分

2010-04-13 52 views
16
void DoWork(int n); 
void DoWork(const int &n); 

請告訴我的diff差分

+0

IIRC,const引用支持多態,但「正常參數」不支持,糾正我,如果我錯了 – Woofas 2017-08-30 05:28:46

回答

20

當你傳遞一個大的結構體/類時,區別更加突出。

struct MyData { 
    int a,b,c,d,e,f,g,h; 
    long array[1234]; 
}; 
void DoWork(MyData md); 
void DoWork(const MyData& md); 

當您使用'正常'參數時,您通過值傳遞參數,因此創建您傳遞的參數的副本。如果使用const引用,則通過引用傳遞它,並且不會複製原始數據。

在這兩種情況下,原始數據都不能從函數內部修改。

編輯:
在某些情況下,如在他的answer指出的Charles Bailey原始數據也許能得到改變。

0

第一種方法通過n由值,即n副本被髮送給該函數。第二個通過n通過引用傳遞,這基本上意味着一個指向函數被調用的指針n被髮送到該函數。

對於像int這樣的整數類型,作爲常量引用傳遞沒有多大意義,因爲引用的大小通常與引用(指針)的大小相同。在製作副本昂貴的情況下,通常最好通過const引用傳遞。

+3

大小不是唯一的問題。通過const引用傳遞允許在函數內部看見原始對象的變化。按值傳遞將函數體與這些更改隔離開來。 – 2010-04-13 05:33:10

+0

@Charles當然,這在某些情況下確實可能是有益的(並且在某些情況下是有害的))。 – 2010-04-13 05:37:11

+0

當通過值與參考引用** int **等類型傳遞類型時,您可以觀察到多線程環境中的不同行爲。 – 2010-04-13 05:55:37

3

隨着

void DoWork(int n); 

n是實際參數值的副本,它是合法的,在函數內改變n值。隨着

void DoWork(const int &n); 

n是實際參數的引用,這是不合法的改變它的值。

2

既然你們沒有提到任何關於const關鍵字...

常量關鍵字修改類型聲明或函數參數的類型,防止改變值的類型。 (來源:MS)

換句話說:通過引用傳遞一個參數將它暴露給被調用者修改。使用const關鍵字可防止修改。

22

重要的區別是,當傳遞const引用時,不會創建新對象。在函數體中,參數實際上是傳入對象的別名。

因爲引用是const引用,所以函數體不能直接更改該對象的值。這具有類似於傳遞值的特性,其中函數體也不能更改傳入的對象的值,在這種情況下,因爲參數是副本。

存在重大差異。如果該參數是const引用,但傳遞它的對象實際上不是const,那麼可以在函數調用本身期間更改該對象的值。

E.g.

int a; 

void DoWork(const int &n) 
{ 
    a = n * 2; // If n was a reference to a, n will have been doubled 

    f(); // Might change the value of whatever n refers to 
} 

int main() 
{ 
    DoWork(a); 
} 

而且如果傳入的對象本來就不是const則函數可以(即使是不明智的話)改變其與投值。

例如

void DoWork(const int &n) 
{ 
    const_cast<int&>(n) = 22; 
} 

如果傳入的對象實際上是const,則會導致未定義的行爲。

當參數由const引用傳遞時,額外的成本包括解引用,更糟糕的對象局部性,編譯優化的機會更少。

當參數按值傳遞並且額外成本是需要創建參數副本的時候。通常這隻在對象類型很大時才需要考慮。

0

首先,沒有cv限定參考的概念。所以術語'const引用'是不正確的,通常用來描述'引用const'。開始談論什麼是最好的。

$ 8.3.2/1-「CV-合格引用不良時形成 cv修飾符通過使用一個typedef(7.1.3)或模板類型參數的 的引入除(14.3 ),在這種情況下,cv限定符 被忽略。「

這裏有

$ 13.1差異 - 「只有在最外層 水平的參數類型定義的常量和揮發性類型說明符以這種方式忽略; const和volatile類型說明符特別是對於任何類型的T, 「指向T的指針」,「指向const T的指針」以及「指向volatile的指針」的指針都是重要的,可用於區分 重載的函數聲明。 T「是 co nsidered不同參數類型,因爲是「參照T,」 「參考爲const T,」和「參照揮發性T.」

void f(int &n){ 
    cout << 1; 
    n++; 
} 

void f(int const &n){ 
    cout << 2; 
    //n++; // Error!, Non modifiable lvalue 
} 

int main(){ 
    int x = 2; 

    f(x);  // Calls overload 1, after the call x is 3 
    f(2);  // Calls overload 2 
    f(2.2);  // Calls overload 2, a temporary of double is created $8.5/3 
} 
2

有三種方法可以在功能

值傳遞
  1. 通過值

    void f(int n){ 
        n=n+10; 
    } 
    
    int main(){ 
        int x = 3; 
        f(x); 
        cout << x<<endl; 
    } 
    

    輸出:3.缺點:當參數x通過f函數,然後編譯器在x的內存中創建一個副本。所以浪費了記憶。

  2. 通過引用傳遞

    void f(int &n){ 
        n=n+10; 
    } 
    
    int main(){ 
        int x = 3; 
        f(x); 
        cout << x<<endl; 
    } 
    

    輸出:13.消除值劣勢通,但如果程序員不希望更改值,然後使用恆定的參考

  3. 恆參考

    void f(const int &n){ 
        n=n+10; // Error: assignment of read-only reference ‘n’ 
    } 
    
    int main(){ 
        int x = 3; 
        f(x); 
        cout << x<<endl; 
    } 
    

    輸出:在n=n+10處拋出錯誤,因爲當我們傳遞const引用參數參數時n它是隻讀參數,不能更改n的值。

+1

你的意思是在f()被調用之後在main()中有print語句嗎?因爲在f()裏面的print語句,我認爲第一個例子的輸出是錯誤的:它應該是13,不是? – Seb 2017-04-20 18:21:00