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

我输入了以下示例:

#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的地址,所以我对 知道中的 x 和 y 有了更多的了解(在那里我知道地址和值)。

先谢谢你!

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

指针与引用 还有一个链接到谷歌编码指南 http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Reference_Arguments,这是相当 useful我觉得(正如我现在理解,这是一种形式的主题口味) ,使更强 > 清楚

97324 次浏览

This is just syntactic sugar to avoid having to use * everytime you reference the argument. You still can use & to have the address of x in f2.

f2 is taking it's arguments by reference, which is essentially an alias for the arguments you pass. The difference between pointer and reference is that a reference cannot be NULL. With the f you need to pass the address (using & operator) of the parameters you're passing to the pointer, where when you pass by reference you just pass the parameters and the alias is created.

Passing by const reference (const double& ref) is preferred when you are not going to change the arguments inside the function, and when you are going to change them, use non-const reference.

Pointers are mostly used when you need to be able to pass NULL to your parameters, obviously you'd need to check then inside your function if the pointer was not NULL before using it.

You should have been able to read x address in both functions.

To do so in f2, you must of course prefix x by a & since there, x is a reference to a double, and you want an address.

A worth noticing difference between references and pointers is that the former cannot be NULL. You must pass something (valid) while when providing a pointer, you must specify in the documentation if passing NULL is allowed/well defined.

Another difference is a matter of readability: using references instead of pointers (when possible) makes the code less cluttered with * and ->.

Another difference that hasn't been mentioned is that you cannot change what a reference refers to. This doesn't make a lot of difference in the function call example shown in the original question.

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 always points to Y and cannot be moved.

References can't be used to index into simple arrays like pointers.

In my head, parameters of functions are always passed by value. Passing an int is easy to imagine, passing a double is just bigger and passing a struct or class could be very big indeed.
But passing a pointer to something, well, you're just passing an address by value. (A pointer is often a convenient size for the CPU just like an int.)
A reference is very similar, and certainly I think of a reference as a pointer, but with syntactic sugar to make it look like the object its referring to has been passed by value.

You can also think of a reference as a const pointer, ie:

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?

So, a pointer does double time: It is a value in its own right, but it can also point to another value when you dereference it, eg: *p.
Also, having reference parameters means that you cannot make them refer to anything else during the lifetime of the function because there's no way to express that.

A reference is supposed not to be able to be initialised with null, but consider this:

void foo(int& i);


int* p = 0;
foo(*p);

This means that pointers should be checked before you use them, but references cannot be checked. The implementation of foo() could try to read from or write to i which will cause an access violation.

In the above example the pointer p should have been checked before being used in the call to foo:

if (p) foo(*p);