我输入了以下示例:
#include <iostream>
double f(double* x, double* y)
{
std::cout << "val x: " << *x << "\n";
std::cout << "val y: " << *y << "\n";
return *x * *y;
}
double f2(double &x, double &y)
{
std::cout << "val x: " << x << "\n";
std::cout << "val y: " << y << "\n";
return x * y;
}
int main()
{
double a, b;
a = 2;
b = 3;
std::cout << f(&a, &b) << "\n";
std::cout << f2(a, b) << "\n";
return 0;
}
在函数f
中,我将x和y声明为指针,我可以使用*x
获取值。在调用f
时,我需要传递我传递的参数的地址,这就是我传递&a, &b
的原因。 f2
是相同的,除了定义不同。
现在我的问题是:它们在内存管理方面是否真的相同?两者都不是传递值的任何副本,而是传递引用?
我想知道f2
,因为我无法在x
中读出f2
的地址,所以我知道更多关于f
中x和y的信息(我知道地址和价值)。
提前致谢!
编辑:好的,谢谢,经过一些研究,我发现了一个非常有用的主题:
Pointer vs. Reference
还有一个指向谷歌编码指南http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Reference_Arguments的链接非常useful
我觉得(正如我现在所理解的那样,它是主题品味的一种形式)可以使清晰
答案 0 :(得分:51)
f2
通过引用获取它的参数,对于您传递的参数,它实质上是别名。指针和引用之间的区别在于引用不能为NULL。使用f
,您需要传递地址(使用&amp;运算符)您传递给指针的参数,当您通过引用传递时,您只需传递参数和别名已创建。
当您不打算更改函数内部的参数时,首选传递const引用(const double& ref
),并且当您要更改它们时,请使用非const引用。
当您需要能够将NULL
传递给参数时,主要使用指针,显然,如果指针在使用之前指针不是NULL
,则需要在函数内部进行检查。< / p>
答案 1 :(得分:12)
这只是语法糖,以避免每次引用参数时都必须使用*
。您仍然可以使用&
在x
中获得f2
的地址。
答案 2 :(得分:9)
未提及的另一个区别是您无法更改引用所指的内容。这在原始问题中显示的函数调用示例中没有太大区别。
int X(10), Y(20);
int *pX = X;
int& rY = Y;
*pX = 15; // change value of X
rY = 25; // change value of Y
pX = Y; // pX now points to Y
rY
始终指向Y
,无法移动。
引用不能用于索引像指针这样的简单数组。
答案 3 :(得分:6)
在我的脑海中,函数的参数总是按值传递。传递int
很容易想象,传递double
只会更大,传递struct
或class
的确可能非常大。
但是将指针传递给某个东西,好吧,你只是按值传递一个地址。(对于CPU来说,指针通常是一个方便的大小,就像int
一样。)
引用非常相似,当然我认为引用是一个指针,但是使用语法糖来使它看起来像它所引用的对象已经通过值传递。
您还可以将引用视为const
指针,即:
int i;
int j;
int* p = &i; // pointer to i
int* const cp = p; // cp points to i, but cp cannot be modified
p = &j; // OK - p is modified to point to j
*cp = 0; // OK - i is overwritten
cp = &j; // ERROR - cp cannot be modified
int& ri = i; // ri refers to i
ri = 1; // i is overwritten
ri = j; // i is overwritten again
// Did you think ri might refer to j?
因此,指针会加倍时间:它本身就是一个值,但是当你取消引用它时它也可以指向另一个值,例如:*p
。
此外,拥有引用参数意味着您无法在函数的生命周期内引用它们,因为无法表达它。
应该无法使用null
初始化引用,但请考虑这一点:
void foo(int& i);
int* p = 0;
foo(*p);
这意味着在使用指针之前应该检查它们,但是不能检查引用。 foo()
的实施可能会尝试读取或写入i
,这会导致访问冲突。
在上面的示例中,指针p
应该在用于调用foo
之前已经:
if (p) foo(*p);
答案 4 :(得分:2)
您应该能够在两个函数中阅读x
地址。
要在f2
中执行此操作,您当然必须在x
前加&
前缀,因为x
是参考到加倍,你想要一个地址。
值得注意的是,引用和指针之间的区别在于前者不能为NULL。在提供指针时,必须传递某些内容(有效),您必须在文档中指定是否允许/定义传递NULL。
另一个区别在于可读性问题:使用引用而不是指针(如果可能)使得代码不会因*
和->
而变得混乱。