对于值和引用,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