1

哪个更好:使用引用void increment(int& x)传递或使用指针传递void increment(int* x)

  1. void increment(int& x)
    {
        x=x+1;
    }
    int main()
    {  
        int n= 2;
        increment(n);
        cout << "Value of n is " << n << '\n';
        return 0;
    }
    

    或者

  2. void increment(int* x)
    {
        *x=*x+1;
    }
    int main()
    {  
        int n= 2;
        increment(&n);
        cout << "Value of n is " << n << '\n';
        return 0;
    }
    
4

4 回答 4

3

没有一个更好。使用指针的优点是它在调用代码中明确表明参数是通过指针传递的,因为参数以&. 使用引用的好处是在调用函数代码中更加自然,不需要所有的*解引用。在内部通常以相同的方式实现,因此应该没有速度优势。

于 2014-03-27T11:10:53.693 回答
1

在不知道您认为“更好”是什么意思的情况下,我只能说它们是不同的。

通过引用传递的优点:

  1. 通过引用传递将阻止您传递nullptr,并使传递无效值变得更加困难。

在性能方面,您不会看到太多差异(如果有的话)。

通过指针传递的优点:

  1. 通过引用传递与 C 不兼容,因此如果您要公开一个希望从 C 调用的函数,则需要使其传递一个指针。

  2. 传递指针允许您传递nullptr/ NULL。虽然将此列为一项好处似乎与将无法做到这一点列为引用的一项好处相矛盾,但这取决于您如何使用您的功能。如果您希望能够指定参数没有值(并且不想包含boost::optional或滚动您自己的值),那么指针是一种惯用的方式。

在这种特定情况下,我更喜欢通过引用传递,因为没有理由在没有有效值的情况下调用函数。

于 2014-03-27T11:33:47.383 回答
0

我个人的经验法则:

  • 对 (in/)out 参数使用指针,因此很明显该函数将更改变量
  • 使用普通参数的引用

因此,在您的情况下,函数increment()明显改变了传入的变量,我将使用指针。如果您使用引用,阅读您的代码的人将不得不跳转到函数的声明以了解函数的副作用。

于 2014-03-27T11:41:13.270 回答
-2

对于面向外部的组件(即在编写第三方将使用的库时),我会使用一个指针,它让用户知道您将修改他们传入的内容。这是以指针取消引用为代价的,它有一个非常非常小的性能成本 - 因为您需要NULL在使用它之前检查指针是否。

对于不打算公开的内部函数,通过引用传递是更可取的,因为它更容易编写并且(同样,只是非常轻微)性能更高。

有clang并且没有优化:

00000000004004c0 <_Z10doThingRefRi>:
  4004c0:       48 89 7c 24 f8          mov    %rdi,-0x8(%rsp)
  4004c5:       48 8b 7c 24 f8          mov    -0x8(%rsp),%rdi
  4004ca:       8b 07                   mov    (%rdi),%eax
  4004cc:       05 01 00 00 00          add    $0x1,%eax
  4004d1:       89 07                   mov    %eax,(%rdi)
  4004d3:       c3                      retq
  4004d4:       66 66 66 2e 0f 1f 84    data32 data32 nopw %cs:0x0(%rax,%rax,1)
  4004db:       00 00 00 00 00

00000000004004e0 <_Z10doThingPtrPi>:
  4004e0:       48 89 7c 24 f8          mov    %rdi,-0x8(%rsp)
  4004e5:       48 81 7c 24 f8 00 00    cmpq   $0x0,-0x8(%rsp)
  4004ec:       00 00
  4004ee:       0f 84 0f 00 00 00       je     400503 <_Z10doThingPtrPi+0x23>
  4004f4:       48 8b 44 24 f8          mov    -0x8(%rsp),%rax
  4004f9:       8b 08                   mov    (%rax),%ecx
  4004fb:       81 c1 01 00 00 00       add    $0x1,%ecx
  400501:       89 08                   mov    %ecx,(%rax)
  400503:       c3                      retq
  400504:       66 66 66 2e 0f 1f 84    data32 data32 nopw %cs:0x0(%rax,%rax,1)
  40050b:       00 00 00 00 00

带有铿锵声和-O3

00000000004004c0 <_Z10doThingRefRi>:
  4004c0:       ff 07                   incl   (%rdi)
  4004c2:       c3                      retq
  4004c3:       66 66 66 66 2e 0f 1f    data32 data32 data32 nopw %cs:0x0(%rax,%rax,1)
  4004ca:       84 00 00 00 00 00

00000000004004d0 <_Z10doThingPtrPi>:
  4004d0:       48 85 ff                test   %rdi,%rdi
  4004d3:       74 02                   je     4004d7 <_Z10doThingPtrPi+0x7>
  4004d5:       ff 07                   incl   (%rdi)
  4004d7:       c3                      retq
  4004d8:       0f 1f 84 00 00 00 00    nopl   0x0(%rax,%rax,1)
  4004df:       00
于 2014-03-27T11:44:37.647 回答