在C ++(也是C)中通过引用传递变量的常用方法如下:
void _someFunction(dataType *name){ // dataType e.g int,char,float etc.
/****
definition
*/
}
int main(){
dataType v;
_somefunction(&v); //address of variable v being passed
return 0;
}
但令我惊讶的是,我注意到当通过引用传递对象时,对象本身的名称服务于目的(不需要&
符号)并且在声明/定义函数期间没有参数前需要*
符号。
以下示例应明确说明:
// this
#include <iostream>
using namespace std;
class CDummy {
public:
int isitme (CDummy& param); //why not (CDummy* param);
};
int CDummy::isitme (CDummy& param)
{
if (¶m == this) return true;
else return false;
}
int main () {
CDummy a;
CDummy* b = &a;
if ( b->isitme(a) ) //why not isitme(&a)
cout << "yes, &a is b";
return 0;
}
我有问题理解为什么这个特殊的待遇是用课堂完成的。即使是几乎像一个类的结构也不会以这种方式使用。 是否将对象名称视为数组的地址?
答案 0 :(得分:51)
似乎让您感到困惑的是,声明为引用传递的函数(使用&
)不会使用实际地址调用,即&a
。
简单的答案是将函数声明为pass-by-reference:
void foo(int& x);
是我们所需要的。然后它会自动通过引用传递。
您现在可以像这样调用此函数:
int y = 5;
foo(y);
和y
将通过引用传递。
您也可以这样做(但为什么会这样?咒语是:尽可能使用引用,需要时使用指针):
#include <iostream>
using namespace std;
class CDummy {
public:
int isitme (CDummy* param);
};
int CDummy::isitme (CDummy* param)
{
if (param == this) return true;
else return false;
}
int main () {
CDummy a;
CDummy* b = &a; // assigning address of a to b
if ( b->isitme(&a) ) // Called with &a (address of a) instead of a
cout << "yes, &a is b";
return 0;
}
输出:
yes, &a is b
答案 1 :(得分:12)
引用实际上是一个指针,含有足够的糖以使其味道很好......;)
但它也使用不同的指针语法,这使得使用引用比指针更容易。因此,在调用带有指针的函数时,我们不需要&
- 编译器会为您处理。并且您不需要*
来获取引用的内容。
要调用引用,别名是一个非常准确的描述 - 它是“同一事物的另一个名称”。因此,当a
作为参考传递时,我们实际上是在传递a
,而不是a
的副本 - 它是通过传递a
的地址完成的(内部) ,但你不必担心它是如何工作的[除非你正在编写自己的编译器,但是在编写自己的编译器时还需要了解很多其他有趣的事情,你不需要担心当你只是编程]。
请注意,引用对int
或class
类型的工作方式相同。
答案 2 :(得分:2)
在上述情况下通过引用传递只是实际对象的alias
。
您将使用不同的名称来引用实际对象。
与references
相比,pointer references
提供了许多优势。
答案 3 :(得分:1)
好吧,好吧,你似乎混淆了pass-by-reference和pass-by-value。此外,C和C ++是不同的语言。 C不支持传递引用。
以下是两个按值传递的C ++示例:
// ex.1
int add(int a, int b)
{
return a + b;
}
// ex.2
void add(int a, int b, int *result)
{
*result = a + b;
}
void main()
{
int result = 0;
// ex.1
result = add(2,2); // result will be 4 after call
// ex.2
add(2,3,&result); // result will be 5 after call
}
当调用 ex.1 时,常量2
和2
将通过在堆栈中创建它们的本地副本来传递给函数。当函数返回时,弹出堆栈,并且传递给堆栈上的函数的任何内容实际上都消失了。
同样的事情发生在 ex.2 中,除了这次,指向int
变量的指针也在堆栈上传递。该函数使用此指针(它只是一个内存地址)来取消引用并更改该内存地址的值,以便“返回”结果。由于函数需要一个内存地址作为参数,因此我们必须为它提供一个,我们通过在变量&
上使用result
“address-of”运算符来实现。
以下是传递引用的两个C ++示例:
// ex.3
int add(int &a, int &b)
{
return a+b;
}
// ex.4
void add(int &a, int &b, int &result)
{
result = a + b;
}
void main()
{
int result = 0;
// ex.3
result = add(2,2); // result = 2 after call
// ex.4
add(2,3,result); // result = 5 after call
}
这两个函数与前两个示例具有相同的最终结果,但不同之处在于它们的调用方式以及编译器如何处理它们。
首先,让我们了解pass-by-reference的工作原理。在pass-by-reference中,通常编译器实现将在最终可执行文件中使用“指针”变量来访问引用的变量,(或者似乎是共识),但这不一定是真的。从技术上讲,编译器可以简单地直接替换引用变量的内存地址,我怀疑这比一般认为的更真实。因此,在使用引用时,它实际上可以生成更高效的可执行文件,即使只是轻微的。
接下来,显然在使用pass-by-reference时调用函数的方式与按值传递没有什么不同,其效果是您可以直接访问函数中的原始变量。这通过隐藏来自调用者的实现细节而具有封装的结果。缺点是你不能改变传入的参数而不改变函数之外的原始变量。在您希望性能改进不需要复制大对象但不想修改原始对象的函数中,请在引用参数前加const
。
最后,与指针变量不同,您无法在创建引用后更改引用,并且必须在创建时初始化它们。
希望我能涵盖所有内容,这一切都是可以理解的。
答案 4 :(得分:0)
我必须补充的一点是C中没有引用。
其次,这是语言语法约定。 &安培; - 是一个地址运算符,但它也意味着一个引用 - 全部取决于美国案例
如果有一些“引用”关键字而不是&amp;你可以写
int CDummy::isitme (reference CDummy param)
但这是C ++,我们应该接受它的优点和缺点......