我了解,与任何其他变量一样,参数的类型确定了参数与其参数的交互。我的问题是,为什么你会引用一个参数,而不引用另一个参数?为什么有些函数的参数是引用,而有些不是?我很难理解这样做的优势,有人可以解释一下吗?
我了解,与任何其他变量一样,参数的类型确定了参数与其参数的交互。我的问题是,为什么你会引用一个参数,而不引用另一个参数?为什么有些函数的参数是引用,而有些不是?我很难理解这样做的优势,有人可以解释一下吗?
通过引用传递的能力存在两个原因:
修改参数的例子:
void get5and6(int *f, int *s) // using pointers
{
*f = 5;
*s = 6;
}
这可以被用作:
int f = 0, s = 0;
get5and6(&f,&s); // f & s will now be 5 & 6
或者
void get5and6(int &f, int &s) // using references
{
f = 5;
s = 6;
}
这可以用作:
int f = 0, s = 0;
get5and6(f,s); // f & s will now be 5 & 6
当我们通过引用传递参数时,我们传递的是变量的地址。通过引用传递类似于传递指针 - 在这两种情况下都传递地址。
例如:
void SaveGame(GameState& gameState)
{
gameState.update();
gameState.saveToFile("save.sav");
}
GameState gs;
SaveGame(gs)
或者
void SaveGame(GameState* gameState)
{
gameState->update();
gameState->saveToFile("save.sav");
}
GameState gs;
SaveGame(&gs);
此外,请了解const
引用的相关知识,当使用它时,函数内的参数将不能被修改。
现在先不考虑指针,但也请谨慎对待此处内容。
引用就是对象本身。当您通过引用传递时,您传递的是该对象。
当您按值传递时,您传递的是对象的副本;另一个对象。它可能具有相同的状态,但它是不同的实例;一个克隆体。
因此,如果您需要在函数内修改对象,则通过引用传递可能是有意义的。
如果您想要从一个相同的孪生开始,并保持原始孪生不受干扰,则通过值传递可能是有意义的。
看看这段代码:
#include<iostream>
struct Foo {
Foo() { }
void describe() const {
std::cout<<"Foo at address "<<this<<std::endl;
}
};
void byvalue(Foo foo) {
std::cout<<"called byvalue"<<std::endl;
foo.describe();
}
void byreference(Foo& foo) {
std::cout<<"called byreference"<<std::endl;
foo.describe();
}
int main() {
Foo foo;
std::cout<<"Original Foo"<<std::endl;
foo.describe();
byreference(foo);
byvalue(foo);
}
按照以下方式编译:g++ example.cpp
运行:./a.out
检查输出(在您的计算机上实际地址可能不同,但要点将保持不变):
Original Foo
Foo at address 0x7fff65f77a0f
called byreference
Foo at address 0x7fff65f77a0f
called byvalue
Foo at address 0x7fff65f779f0
注意,按引用调用
的地址与原始 Foo
的地址相同(都是0x7fff65f77a0f
)。而按值调用
的地址则不同(它是0x7fff65f779f0
)。
再来一步。将代码修改如下:
#include<iostream>
#include<unistd.h> // for sleeping
struct Foo {
Foo() { }
Foo(const Foo&) {
sleep(10); // assume that building from a copy takes TEN seconds!
}
void describe() const {
std::cout<<"Foo at address "<<this<<std::endl;
}
};
void byvalue(Foo foo) {
std::cout<<"called byvalue"<<std::endl;
foo.describe();
}
void byreference(Foo& foo) {
std::cout<<"called byreference"<<std::endl;
foo.describe();
}
int main() {
Foo foo;
std::cout<<"Original Foo"<<std::endl;
foo.describe();
byreference(foo);
byvalue(foo);
}
以相同的方式编译它,并注意输出内容(注释不会在输出中显示,仅为清晰起见):
Original Foo
Foo at address 0x7fff64d64a0e
called byreference
Foo at address 0x7fff64d64a0e # this point is reached "immediately"
called byvalue # this point is reached TEN SECONDS later
Foo at address 0x7fff64d64a0f
所以,这段代码的目的是夸大复制的成本:当你通过引用调用时,并未产生这个成本。而当你通过值调用时,需要等待十秒钟。
注意:我的代码是在OS X 10.7.4中使用GCC 4.8.1编译的。如果你在Windows上,可能需要使用不同于unitsd.h
的东西来使sleep
调用起作用。
也许这会有所帮助。
按引用传递变量与手动通过指针传递变量相同,但按引用传递变量不会让用户处理“容易混淆”的指针。