使用指针和解引用指针通过引用传递

时间:2014-03-27 11:01:36

标签: c++ pass-by-reference pass-by-pointer

哪一个更好:通过参考传递使用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 个答案:

答案 0 :(得分:3)

没有比这更好的了。使用指针的优点是它在调用代码中明确指出参数是由指针传递的,因为参数前面有&。使用引用的优点是它在调用函数代码中更自然,没有所有*解引用。在内部通常以相同的方式实现,因此应该没有速度优势。

答案 1 :(得分:1)

不知道你的想法&#34;更好&#34;意思是,我只能说它们是不同的。

通过引用传递的优点:

  1. 通过引用传递将阻止您传递nullptr,并且会使传递无效值变得更加困难。
  2. 在表现方面,你不会看到太多(如果有的话)差异。

    通过指针传递的优点:

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

    2. 通过指针可以传递nullptr / NULL。虽然列出这个好处似乎与列出无法将此作为参考的好处列出相反,但这取决于您如何使用您的功能。如果想要能够指定参数没有值(并且不想包含boost::optional或滚动自己的参数),那么指针就是惯用的这样做的方式。

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

答案 2 :(得分:0)

我个人的经验法则:

  • 使用(in /)输出参数的指针,以便立即清除该函数将更改变量
  • 使用正常参数的参考

所以在你的情况下,函数increment()明显改变传入的变量,我会使用指针。如果您使用引用,那么阅读代码的人必须跳转到函数的声明,以了解函数的副作用。

答案 3 :(得分:-2)

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

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

铿锵而没有优化:

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

使用clang和-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