2011-11-18 69 views
0

只是一個簡單的問題傳遞構造函數參數介紹這樣一個功能:通過值或引用

class Test { 
    public: 
    Test(vector<int>& v) { 
     v_ = v; 
    } 
    private: 
    std::vector<int> v_; 
}; 

有什麼用Test(vector<int>& v)Test(vector<int> v)之間的區別?我似乎知道,第一個應該更快,因爲它是通過參考。但我不太確定是否有其他差異。

+2

這與rvalue refs沒有關係。 – Xeo

回答

2

不同的是,與Test(vector<int>& v)(其順便說一句是一個左值參考)v指的是原始對象,而具有Test(vector<int> v)你有一個副本。以下示例代碼演示用int的差和一個正常功能(注意,對於int,通過按值實際上更快!):

#include <iostream> 

int global_i; 

void pass_by_value(int i) 
{ 
    std::cout << "pass by value:\n"; 
    std::cout << "initially: i = " << i << ", global_i = " << global_i << "\n"; 
    i++; 
    std::cout << "after i++: i = " << i << ", global_i = " << global_i << "\n"; 
    global_i++; 
    std::cout << "after global_i++: i = " << i << ", global_i = " << global_i << "\n"; 
} 

void pass_by_reference(int& i) 
{ 
    std::cout << "pass by reference:\n"; 
    std::cout << "initially: i = " << i << ", global_i = " << global_i << "\n"; 
    i++; 
    std::cout << "after i++: i = " << i << ", global_i = " << global_i << "\n"; 
    global_i++; 
    std::cout << "after global_i++: i = " << i << ", global_i = " << global_i << "\n"; 
} 

void pass_by_const_reference(int const& i) 
{ 
    std::cout << "pass by const reference:\n"; 
    std::cout << "initially: i = " << i << ", global_i = " << global_i << "\n"; 
    // i++; not allowed! 
    // std::cout << "after i++: i = " << i << ", global_i = " << global_i << "\n"; 
    global_i++; 
    std::cout << "after global_i++: i = " << i << ", global_i = " << global_i << "\n"; 
} 

int main() 
{ 
    global_i = 1; 
    pass_by_value(global_i); 

    global_i = 1; 
    pass_by_reference(global_i); 

    global_i = 1; 
    pass_by_const_reference(global_i); 
} 

的這個輸出是:

pass by value: 
initially: i = 1, global_i = 1 
after i++: i = 2, global_i = 1 
after global_i++: i = 2, global_i = 2 
pass by reference: 
initially: i = 1, global_i = 1 
after i++: i = 2, global_i = 2 
after global_i++: i = 3, global_i = 3 
pass by const reference: 
initially: i = 1, global_i = 1 
after global_i++: i = 2, global_i = 2 

正如您所看到的,通過值調用,參數和傳遞的變量完全分離。遞增參數不會更改傳遞的變量,並且遞增傳遞的變量不會更改參數。另一方面,通過引用傳遞,參數只是訪問傳遞的變量:無論你增加哪一個因爲有效,它們都是相同的。通過const引用傳遞,它們也是一樣的,但是你不允許將參數清除(雖然有解決方法,但是)。但是,該論點仍然反映了對傳遞變量的任何更改。

這些是功能上的差異。但是還有一些區別:對於按值傳遞並通過const引用傳遞,可以使用右值,如call_by_value(2)call_by_const_reference(2)。對於按值調用,很明顯會發生什麼:參數的值爲2,就是這樣。但是對於const引用,有一個預期的對象(例如,您可以在函數中獲取該對象的地址)。因此在這種情況下會創建一個臨時對象。對於非const引用的調用,你不能傳遞一個右值。

C++ 11在混合中增加了另一種類型,即右值引用。那些用&&而不是&表示。在函數內部,它們的行爲與普通(左值)引用完全相同,但它們的區別在於它們可以綁定到右值,即使它們不是常量。此外,如果您將它們用作返回類型,則調用表達式將是右值類型,就像您已返回值一樣。特別是,你將無法將函數的結果返回給函數期望左值引用,就像你不能用文字2那樣做。

0

代碼中沒有右值引用,只是大量不必要的複製。

但是,由於我們的話題,下面就來與移動語義寫的正確方法:

Test(std::vector<int> v) // by value! 
: v_(std::move(v)) 
{ 
} 

在預11的世界,下一個最好的辦法是採取以const參數引用並複製:

Test(std::vector<int> const & v) 
: v_(v) 
{ 
} 
+0

對不起,你是否介意幫助我編輯帖子,以便更好地反映主題? :) – derekhh

+0

也許「按值或通過引用傳遞構造函數參數」將是一個很好的問題標題。但是你也錯過了使用初始化列表。無論如何,這裏沒有什麼深入的,這只是標準的東西。你有什麼具體的擔憂嗎? –

+0

其實我不太確定什麼是「通過引用」。我之前的知識告訴我,它實際上意味着像「傳遞地址」到目標,但我不確定,例如在這種情況下,如果我們破壞v,v_會發生什麼? – derekhh