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

发布于 2024-11-04 07:13:32 字数 1375 浏览 3 评论 0原文

我输入了以下示例:

#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 在 f 中(我知道地址和值)。

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

指针与引用 还有一个指向 Google 编码指南的链接 http://google-styleguide.googlecode .com/svn/trunk/cppguide.xml#Reference_Arguments 我觉得它非常有用(据我现在的理解,这是一种主题形式味道)使更清晰

I typed the following example:

#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;
}   

In the function f I declare x and y as pointers of which I can get the value by using *x. When calling f I need to pass the address of my passed arguments, that is why I pass &a, &b. f2 is the same except the definition is different.

Now my question is: Are they both really the same concerning memory management? Both not making any copy of the passed value but instead passing a reference?
I wonder about f2 because I couldn't read out the address of x in f2 so I know more about x and y in f (there I know address AND value).

Edit: After doing some more research, I found a quite useful topic:

Pointer vs. Reference
There's also a link to google coding guidelines http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Reference_Arguments which is quite useful I feel (as I understood now, it's a form of subject taste) to make more clear

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

旧人哭 2024-11-11 07:13:33

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

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

当您需要能够将 NULL 传递给参数时,通常会使用指针,显然您需要在使用之前在函数内部检查指针是否不为 NULL它。

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.

怂人 2024-11-11 07:13:33

这只是语法糖,以避免每次引用参数时都必须使用 *。您仍然可以使用 & 来获取 f2x 的地址。

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.

淡忘如思 2024-11-11 07:13:33

在我看来,函数的参数总是按值传递。传递 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);

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);
黒涩兲箜 2024-11-11 07:13:33

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

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

引用不能用于索引简单数组(如指针)。

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.

呆° 2024-11-11 07:13:33

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

要在 f2 中执行此操作,您当然必须在 x 前面添加 &,因为 x 是一个引用双精度值,并且您需要一个地址

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

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

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 ->.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文