只是一個簡單的問題傳遞構造函數參數介紹這樣一個功能:通過值或引用
class Test {
public:
Test(vector<int>& v) {
v_ = v;
}
private:
std::vector<int> v_;
};
有什麼用Test(vector<int>& v)
和Test(vector<int> v)
之間的區別?我似乎知道,第一個應該更快,因爲它是通過參考。但我不太確定是否有其他差異。
只是一個簡單的問題傳遞構造函數參數介紹這樣一個功能:通過值或引用
class Test {
public:
Test(vector<int>& v) {
v_ = v;
}
private:
std::vector<int> v_;
};
有什麼用Test(vector<int>& v)
和Test(vector<int> v)
之間的區別?我似乎知道,第一個應該更快,因爲它是通過參考。但我不太確定是否有其他差異。
不同的是,與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那樣做。
代碼中沒有右值引用,只是大量不必要的複製。
但是,由於我們的話題,下面就來與移動語義寫的正確方法:
Test(std::vector<int> v) // by value!
: v_(std::move(v))
{
}
在預11的世界,下一個最好的辦法是採取以const參數引用並複製:
Test(std::vector<int> const & v)
: v_(v)
{
}
這與rvalue refs沒有關係。 – Xeo