C++:参数传递"passed by reference"
C++: Argument Passing "passed by reference"
我理解与任何其他变量一样,参数的类型决定了参数与其参数之间的交互。 我的问题是,为什么你会引用参数与为什么不引用参数背后的原因是什么? 为什么有些函数参数是引用的,有些不是? 难以理解这样做的好处,有人可以解释一下吗?
通过引用传递的能力存在有两个原因:
- 修改函数参数的值
- 避免出于性能原因复制对象
修改参数的示例
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
参考资料。使用它时,无法在函数中修改参数。
这篇文章对我帮助很大。
请暂时忘记指针。并对此持保留态度。
引用是对象。通过引用传递时,传递对象。
按值传递时,传递对象的副本;另一个对象。它可能具有相同的状态,但它是一个不同的实例;克隆。
因此,如果您符合以下条件,则通过引用传递可能是有意义的:
- 需要修改函数内部的对象
- 不需要(或想要)修改对象,但希望避免仅仅为了将其传递给函数而复制它。这将是一个
const
参考。
符合以下条件,则按值传递可能是有意义的:
- 想从同卵双胞胎开始,让原来的双胞胎不受干扰
- 不关心复制对象的成本(例如,除非我想修改它,否则我不会通过引用传递
int
)。
在这里,看看这段代码:
#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
请注意called byreference
地址与Original Foo
地址相同(两者都0x7fff65f77a0f
)。请注意called byvalue
地址的不同之处(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
因此,代码旨在夸大副本的成本:当您通过引用调用时,不会产生此成本。当您按值调用时,您必须等待十秒钟。
注意:我的代码是使用 GCC 4.8.1 在 OS X 10.7.4 中编译的。如果您在窗口中,则可能需要与unitsd.h
不同的内容才能使sleep
调用正常工作。
也许这会有所帮助。
使用按引用传递的优点:您不必创建数据的副本,只需在内存中传递指向它的指针即可。(巨大的性能胜利,想想如果你有一个你传递的巨大物体)。您可以"返回"多个值 我知道 c/c++ 中的一些函数返回一个数字,其中一个参数是指向纵数据的指针。
使用按引用传递的缺点:您必须小心修改传递的数据,因为它可能会导致您可能想要或可能不希望的副作用。
通过引用同样是通过指针手动传递变量,但通过引用不会让用户处理"容易搞砸"的指针。
- 转到特定页面后,如何将滑动视图的当前索引设置为选项卡栏"by reference"的当前索引?
- 为什么我们必须在C++中将值而不是地址传递到"call by reference"函数中?
- C 语言和 C++ 中的"pass by reference"究竟有什么区别?
- 无法找出 Java 等效的 "passing by reference" 在C++解决这个问题,以及最好的解决方法
- 为什么CPPCHECK说"Function parameter should be passed by reference"?
- std::thread pass-by-reference调用复制构造函数
- getters by reference和getters by copy这两个不同的词
- 为什么隐式"lambda to function pointer conversion"禁止"by reference"捕获静态成员?
- Lambda by reference
- C++:参数传递"passed by reference"
- 为什么程序员说"pass by reference"真的很"passing references by value?"为什么这很重要?
- 提高ptr_vector处理去除"by reference"
- 将特征类型与 boost::bind 一起使用是否会自动违反 Eigen 的"only pass by reference"规则?
- 除了语法,"call by reference"和"call by pointer"在内存方面C++有什么区别吗?
- 采用"pass by reference"值的递归函数的包装函数
- c++ Singleton by reference use
- "return-by-reference"或"pass-by-reference"参数何时与constexpr兼容?
- 如何在 C 语言中模仿C++ "pass array(pointer) by reference"?
- 两个方法声明都"pass by reference"吗?
- Visual Studio 2010 - C++ 函数在销毁后返回有效的'by reference'对象