C++:参数传递“通过引用传递”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19827119/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C++: Argument Passing "passed by reference"
提问by Tyler
I understand as with any other variable, the type of a parameter determines the interaction between the parameter and its argument. My question is that what is the reasoning behind why you would reference a parameter vs why you wouldn't? Why are some functions parameters reference and some are not? Having trouble understanding the advantages of doing so, could someone explain?
我理解与任何其他变量一样,参数的类型决定了参数与其自变量之间的交互。我的问题是,为什么要引用参数与为什么不引用的原因是什么?为什么有些函数参数引用,有些则不是?无法理解这样做的好处,有人可以解释一下吗?
回答by gldraphael
The ability to pass by reference exists for two reasons:
存在通过引用传递的能力有两个原因:
- To modify the value of the function arguments
- To avoid make copies of an object for performance reasons
- 修改函数参数的值
- 为了避免出于性能原因复制对象
Example for modifying the argument
修改参数的示例
void get5and6(int *f, int *s) // using pointers
{
*f = 5;
*s = 6;
}
this can be used as:
这可以用作:
int f = 0, s = 0;
get5and6(&f,&s); // f & s will now be 5 & 6
OR
或者
void get5and6(int &f, int &s) // using references
{
f = 5;
s = 6;
}
this can be used as:
这可以用作:
int f = 0, s = 0;
get5and6(f,s); // f & s will now be 5 & 6
When we pass by reference, we pass the address of the variable. Passing by reference is similar to passing a pointer - only the address is passed in both cases.
当我们通过引用传递时,我们传递的是变量的地址。通过引用传递类似于传递指针 - 在这两种情况下都只传递地址。
For eg:
例如:
void SaveGame(GameState& gameState)
{
gameState.update();
gameState.saveToFile("save.sav");
}
GameState gs;
SaveGame(gs)
OR
或者
void SaveGame(GameState* gameState)
{
gameState->update();
gameState->saveToFile("save.sav");
}
GameState gs;
SaveGame(&gs);
由于只传递地址,变量的值(对于巨大的对象可能非常大) doesn't need to be copied不需要复制。因此,通过引用传递可以提高性能,尤其是在以下情况下:
- The object passed to the function is huge (I would use the pointer variant here so that the caller knows the function might modify the value of the variable)
- The function could be called many times (eg. in a loop)
- 传递给函数的对象很大(我会在这里使用指针变量,以便调用者知道该函数可能会修改变量的值)
- 该函数可以被多次调用(例如在循环中)
Also, read on const
references. When it's used, the argument cannot be modified in the function.
另外,请阅读const
参考资料。使用时,不能在函数中修改参数。
回答by Escualo
Please forget about pointers for now. And take this with a grain of salt.
请暂时忘记指针。把这个和一粒盐一起吃。
A reference isthe object. When you pass by reference, you pass theobject.
引用是对象。当您通过引用传递时,您传递的是对象。
When you pass by value, you pass a copyof the object; anotherobject. It may have the same state, but it is a differentinstance; a clone.
按值传递时,传递的是对象的副本;另一个对象。它可能具有相同的state,但它是不同的实例;一个克隆人。
So, it may make sense to pass by reference if you:
因此,如果您:
- need to modify theobject inside the function
- do not need (or want) to modify theobject, but would like to avoid copying it just to pass it to a function. This would be a
const
reference.
- 需要修改的函数内部对象
- 不需要(或希望)修改的对象,但想避免复制它只是将它传递给一个函数。这将是一个
const
参考。
And it may make sense to pass by value if you:
如果您:
- want to start from an identicaltwin, and leave the originaltwin undisturbed
- do not care about the cost of copying the object (for example, I would not pass an
int
by reference unlessI wanted to modify it).
- 想从同卵双胞胎开始,让原来的双胞胎不受干扰
- 不关心复制对象的成本(例如,除非我想修改它,否则我不会通过
int
引用传递)。
Here, have a look at this code:
在这里,看看这段代码:
#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);
}
And compile it like this: g++ example.cpp
并像这样编译它: g++ example.cpp
Run it: ./a.out
运行: ./a.out
And check the output (the actual addresses may be different in your computer, but the point will remain):
并检查输出(实际地址可能在您的计算机中有所不同,但重点将保留):
Original Foo
Foo at address 0x7fff65f77a0f
called byreference
Foo at address 0x7fff65f77a0f
called byvalue
Foo at address 0x7fff65f779f0
Notice how the called byreference
address is the same as the Original Foo
address (both are 0x7fff65f77a0f
). And notice how the called byvalue
address is different(it is 0x7fff65f779f0
).
注意called byreference
地址如何与地址相同Original Foo
(两者都是0x7fff65f77a0f
)。并注意called byvalue
地址是如何不同的(它是0x7fff65f779f0
)。
Take it up a notch. Modify the code to look as follows:
把它提升一个档次。修改代码如下:
#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);
}
Compile it the same way, and notice the output (comments not in the output; included for clarity):
以同样的方式编译它,并注意输出(注释不在输出中;为了清楚起见,包括在内):
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
So, the code is meant to exaggerate the cost of a copy: when you called by reference this cost was NOT incurred. When you called by value you had to wait for ten seconds.
因此,该代码旨在夸大副本的成本:当您通过引用调用时,不会产生此成本。当您按值调用时,您必须等待十秒钟。
Note: my code was compiled in OS X 10.7.4 using GCC 4.8.1. If you are in windows you may need something different from unitsd.h
to make the sleep
call work.
注意:我的代码是在 OS X 10.7.4 中使用 GCC 4.8.1 编译的。如果您在 Windows 中,您可能需要一些不同的东西unitsd.h
才能使sleep
呼叫正常工作。
Maybe this helps.
也许这有帮助。
回答by dbarnes
Pros of using pass by reference: you don't have to create a copy of the data that you are passing just the pointer to it in memory. (huge performance win think if you had a massive object that you passed around). You can "return" multiple values I know some functions in c/c++ return a number and one of the params is a pointer to the data that get's manipulated.
使用按引用传递的优点:您不必创建数据的副本,只需将指针传递到内存中即可。(如果你有一个巨大的对象,你就会获得巨大的性能胜利)。您可以“返回”多个值,我知道 c/c++ 中的某些函数会返回一个数字,其中一个参数是指向所操作数据的指针。
Cons of using pass by reference: you have to be careful modifying the data passed as it could cause side effects that you may or may not want.
使用通过引用传递的缺点:您必须小心修改传递的数据,因为它可能会导致您可能想要也可能不想要的副作用。
回答by TerrenceSun
By reference is equally to manually pass the variable by pointer, but by reference will not let user to handle the "easy to mess up" pointer.
通过引用同样是手动通过指针传递变量,但是通过引用不会让用户处理“容易搞砸”的指针。