對於值和引用,C++不具有與Java相同的語義。起初,每種類型都有可能通過複製或通過引用或通過地址傳遞(然而,您可以通過隱藏複製構造函數來防止類型通過複製傳遞)。
與Java的「通過引用」傳遞關係最密切的傳遞類型是通過指針。這裏是三個的示例:
void foo(std::string bar); // by copy
void foo(std::string& bar); // by reference
void foo(std::string* bar); // by address
作爲邊注,路過副本總是大於通過引用或指針傳遞用於比指針的大小較大的類型更昂貴。出於這個原因,您也可能更喜歡傳遞const
引用,這將允許您讀取對象而不必複製它。
void foo(const std::string& bar); // by const reference
但是,這是非常棘手的,你需要知道Java的細微之處,以正確地決定你想要在C++中。在Java中,你實際上並不是通過引用來傳遞對象:你通過複製來傳遞對象引用。也就是說,如果將新對象分配給參數,則父範圍的對象不會更改。在C++中,這通過地址比通過引用更加緊密地匹配傳遞對象。這裏有一個如何這是很重要的一個例子:
// Java using "object references":
public static void foo(String bar)
{
bar = "hello world";
}
public static void main(String[] argv)
{
String bar = "goodbye world";
foo(bar);
System.out.println(bar); // prints "goodbye world"
}
// C++ using "references":
void foo(std::string& bar)
{
bar = "hello world";
}
int main()
{
std::string bar = "goodbye world";
foo(bar);
std::cout << bar << std::endl; // prints "hello world"
}
// C++ using pointers:
void foo(std::string* bar)
{
bar = new std::string("goodbye world");
delete bar; // you don't want to leak
}
int main()
{
std::string bar = "goodbye world";
foo(&bar);
std::cout << bar << std::endl; // prints "hello world"
}
換句話說,當你在C++中使用引用,你真的與你們打交道通過相同的變量。您對它做的任何更改,甚至是分配,都會反映到父範圍中。 (這部分是由於C++如何處理賦值操作符)。使用指針,您會得到一個與您使用Java引用的行爲關係更密切的行爲,代價是可能必須通過一元運算符&
獲取對象地址(參見我的示例中的foo(&bar)
),需要使用->
運算符來訪問成員,以及使用運算符重載的一些額外複雜性。
另一個值得注意的區別是,由於使用by-reference參數與by-copy參數的使用在語法上密切相關,所以函數應該能夠假設您通過引用傳遞的對象是有效的。儘管通常可以將引用傳遞給NULL
,但是非常不鼓勵,因爲實現它的唯一方法是取消引用NULL
,該引用具有未定義的行爲。因此,如果您需要能夠通過NULL
作爲參數,則您更願意按地址而不是按引用傳遞參數。
大多數情況下,當您想從函數修改參數時,您希望通過引用而不是地址傳遞,因爲它更「C++友好」(除非需要NULL
值),即使它不完全像Java所做的那樣。
這功課嗎?您可能想要閱讀C的*(間接)和&(引用)操作符。 – eggyal 2011-05-07 15:44:18
@eggyal C和C++都沒有引用操作符 - &是操作符的地址。 – 2011-05-07 15:51:03
@unapersson:有什麼區別? :s – eggyal 2011-05-07 16:00:13