用&声明的函数参数之间的区别和*在C ++中

时间:2011-04-28 09:49:28

标签: c++ function pointers pass-by-reference

我输入了以下示例:

#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我觉得(正如我现在所理解的那样,它是主题品味的一种形式)可以使清晰

5 个答案:

答案 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只会更大,传递structclass的确可能非常大。
但是将指针传递给某个东西,好吧,你只是按值传递一个地址(对于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。

另一个区别在于可读性问题:使用引用而不是指针(如果可能)使得代码不会因*->而变得混乱。