哪一个更好:通过参考传递使用void increment(int& x)
或通过指针使用void increment(int* x)
?
void increment(int& x)
{
x=x+1;
}
int main()
{
int n= 2;
increment(n);
cout << "Value of n is " << n << '\n';
return 0;
}
或
void increment(int* x)
{
*x=*x+1;
}
int main()
{
int n= 2;
increment(&n);
cout << "Value of n is " << n << '\n';
return 0;
}
答案 0 :(得分:3)
没有比这更好的了。使用指针的优点是它在调用代码中明确指出参数是由指针传递的,因为参数前面有&
。使用引用的优点是它在调用函数代码中更自然,没有所有*
解引用。在内部通常以相同的方式实现,因此应该没有速度优势。
答案 1 :(得分:1)
不知道你的想法&#34;更好&#34;意思是,我只能说它们是不同的。
通过引用传递的优点:
nullptr
,并且会使传递无效值变得更加困难。在表现方面,你不会看到太多(如果有的话)差异。
通过指针传递的优点:
通过引用传递与C不兼容,因此如果您正在暴露一个您希望从C调用的函数,则需要使它通过指针。
通过指针可以传递nullptr
/ NULL
。虽然列出这个好处似乎与列出无法将此作为参考的好处列出相反,但这取决于您如何使用您的功能。如果想要能够指定参数没有值(并且不想包含boost::optional
或滚动自己的参数),那么指针就是惯用的这样做的方式。
在这种特定情况下,我更希望通过引用传递,因为没有理由在没有有效值的情况下调用函数。
答案 2 :(得分:0)
我个人的经验法则:
所以在你的情况下,函数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