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

Difference between function arguments declared with & and * in C++

本文关键字:函数 参数 之间 声明 中用 C++      更新时间:2023-10-16

我键入了以下示例:

#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,因为我无法读出f2x的地址,所以我对f中的 x 和 y 有了更多的了解(我知道地址和值(。

编辑:在做了更多的研究之后,我发现了一个非常有用的话题:

指针与引用还有一个指向谷歌编码指南的链接 http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Reference_Arguments 我觉得这很useful(正如我现在所理解的,这是一种主题品味的形式(来更清楚地说明

f2通过

引用获取其参数,这本质上是您传递的参数的别名。 指针和引用之间的区别在于引用不能为 NULL。 使用f,您需要将要传递的参数的地址(使用和运算符(传递给指针,当您通过引用传递时,您只需传递参数并创建别名。

当您不打算更改函数内的参数时,首选通过常量引用 (const double& ref( 传递,当您要更改它们时,请使用非常量引用。

指针主要用于需要能够NULL传递给参数时,显然您需要在函数内部检查指针是否在使用之前未NULL

这只是

语法糖,以避免每次引用参数时都必须使用*。您仍然可以使用 &f2 中拥有 x 的地址。

在我的脑海中,函数的参数总是按值传递的。 通过一个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);

另一个未提及的区别是您无法更改引用的内容。这在原始问题中显示的函数调用示例中没有太大区别。

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,无法移动。

引用不能用于索引到指针等简单数组中。

您应该能够在这两个函数中读取x地址。

要在 f2 中这样做,您当然必须以&作为x前缀,因为在那里,x是对双精度的引用,并且您想要一个地址

引用和指针之间值得注意的区别是前者不能为 NULL。您必须传递某些内容(有效(,而在提供指针时,您必须在文档中指定是否允许/明确定义传递 NULL。

另一个区别是可读性问题:使用引用而不是指针(如果可能(使代码不那么混乱,*->