【问题标题】:What's the Difference Between func(int &param) and func(int *param)?func(int &param) 和 func(int *param) 有什么区别?
【发布时间】:2010-09-16 11:23:48
【问题描述】:

在下面的代码中,amp_swap()star_swap() 似乎都在做同样的事情。那么为什么有人会更喜欢使用其中一种呢?哪一个是首选符号,为什么?还是只是口味问题?

#include <iostream>

using namespace std;

void amp_swap(int &x, int &y)
{
    int temp = x;
    x = y;
    y = temp;
}

void star_swap(int *x, int *y)
{
    int temp = *x;
    *x = *y;
    *y = temp;
}

int main()
{
    int a = 10, b = 20;
    cout << "Using amp_swap(): " << endl;
    amp_swap(a, b);
    cout << "a = " << a << ", b = " << b << endl;
    cout << "Using star_swap(): " << endl;
    star_swap(&a, &b);
    cout << "a = " << a << ", b = " << b << endl;
    return 0;
}

感谢您的宝贵时间!


另见

Difference between pointer variable and reference variable in C++

【问题讨论】:

标签: c++ pointers reference


【解决方案1】:

它们与计算机完全相同。但是,一个是引用(&),另一个是指针(*)

http://www.google.com/search?hl=en&q=pointers+vs+references&btnG=Google+Search&aq=1&oq=pointers+vs

我相信它们都有各自的用途 - 与指针一样,您可以进行更多的低级内存操作,但引用的语法更容易。

:)

【讨论】:

    【解决方案2】:

    (int *param) 是较旧的 C 风格,使用直接内存指针。 (int &amp;param) 是现代 C++ 风格,使用引用(原始指针的类型安全包装器)。如果您使用的是 C++,您可能应该使用参考。

    【讨论】:

      【解决方案3】:

      一个使用引用,一个使用指针。

      我会使用带引用的那个,因为你不能传递 NULL 引用(而你可以传递 NULL 指针)。

      如果你这样做:

      star_swap(NULL, NULL);
      

      您的应用程序将崩溃。而如果你尝试:

      amp_swap(NULL, NULL); // This won't compile
      

      除非您有充分的理由使用指针,否则请始终使用引用。

      查看此链接:http://www.google.co.uk/search?q=references+vs+pointers

      【讨论】:

      • 这不是全部,你只是说通过引用传递意味着你不能传递NULL。这可能是真的,但这并不是参考的全部。
      • 不,但我并没有说这是一篇关于什么是引用的完整、简洁的文章。我只是指出影响所提供源代码的最大差异。对于 OP,我建议阅读一些关于什么是引用的文章。
      • 您可以将 null 传递给引用,但这并不容易。
      • 是的,显然你可以得到一个空引用,但你必须跳过一个箍来做到这一点。例如MyClass *pClass = nullptr; MyFunc(*pClass);
      • 这是未定义的行为,应不惜一切代价避免。
      【解决方案4】:

      引用不能为 NULL。因此,使用第一个版本会阻止调用者将 NULL 作为函数参数之一传递。

      无法重新分配引用以指向其他内容。所以,你知道在函数 amp_swap() 中,xy 总是指同一个东西。在指针版本中,您可以(在更复杂的函数中)重新分配 xy 以指向其他内容,这可能会使逻辑不太清晰(是的,您可以将参数声明为 int *const x 以避免这种情况重新分配)。

      参考版本的函数体看起来更干净,因为它没有那么多星星。

      【讨论】:

        【解决方案5】:

        这不是符号问题。

        向函数传递参数有3种方式:

        1. 按价值计算
        2. 参考
        3. 按指针

        amp_swap 中,您通过引用传递实际参数。这仅在 C++ 中引入并有效。

        star_swap 中,您使用指针传递参数。这是最初的 C-way。

        基本上,如果您使用 C++,建议使用引用,因为它对变量更具可读性。如果您需要指针,请务必使用它们。

        并且记住在声明带有引用的方法时使用&amp; 符号,否则会产生错误。如果您没有在amp_swap 中声明引用,该函数将不会交换任何内容。因为这种方式您使用方法 1(仅传递参数值)并且在函数中将创建两个新的自动变量,它们仅存在于函数的范围内。这样就不会触及原来的外部变量了。

        【讨论】:

          【解决方案6】:

          如果您查看here,您会发现指针与引用的描述,最有用的信息最初来自此引用。

          C++ 不允许您声明“const 引用”,因为引用本质上是 > const。换句话说,一旦你绑定一个引用来引用一个对象,你就不能重新绑定它来引用另一个对象。声明引用后,没有重新绑定引用的符号。

          以下绑定 ri 以引用 i。

          int &amp;ri = i;

          然后是赋值如:

          ri = j;

          不会将 ri 绑定到 j。它将j中的值赋给ri所引用的对象,即i。

          希望这更清楚。

          【讨论】:

            【解决方案7】:

            也可以使用指针版本优于参考版本的参数。事实上,从文档的角度来看,它是优越的,因为调用者知道输入参数将被修改。比较这两个调用:

            swap(a, b);
            swap(&a, &b); // This cries “will modify arguments” loud and clear.
            

            当然,对于swap 函数,这一点没有实际意义;每个人都知道它的论点将被修改。还有其他情况不太明显。正是出于这个原因,C# 有 ref 关键字。在 C# 中,上述内容必须如下所示:

            swap(ref a, ref b);
            

            当然,还有其他方法可以记录这种行为。使用指针是一种有效的方法。

            【讨论】:

            • 我有点不同意:如果你使用或阅读使用函数“doSomething”的代码,那么你应该知道它的接口/契约。您的版本,即使用指针,只是使编码器能够避免读取函数的原型,代价是启用传递 NULL 指针。
            • 我也不同意这种心态。函数的名称可以使其同样清晰。 "swap" 告诉我它正在 交换 东西。哪个尖叫“将修改 args”同样清楚。
            【解决方案8】:
            • 与指针一样,引用可以修改作为参数传递的数据
            • 和指针一样,引用支持多态性
            • 与指针不同,引用永远不会为 NULL(您仍然可以通过一些 hack 来实现这一点,但是,这更像是破坏而不是编码......)
            • 与指针不同,引用在 const 时启用类型提升(即,具有接受 char * 的 std::string 参数的函数)
            • 与指针不同,不能重新分配引用:无法在代码的某个位置修改它,而指针可以在一个点指向 A,在另一个点指向 B,而在另一个点又指向 NULL .而且您不希望 ++ 错误地应用于您的指针...
            • 与指针不同,引用使数据的操作变得像使用“int”或“bool”之类的原语一样简单,而无需一直使用 * 运算符

            由于这些原因,在 C++ 中,引用使用通常是默认的,而指针是例外。

            因此,为了保持一致性,在您建议的两个“交换”函数之间,我将使用 amp_swap 并从源中删除星号(只是为了确保没有人会使用它并在源中添加无用的指针代码)...

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-07-18
              • 2022-01-23
              • 1970-01-01
              • 2018-05-01
              • 1970-01-01
              相关资源
              最近更新 更多