关于指针与引用传递的效率问题

关于指针与引用传递的效率问题

关于指针与引用传递的效率问题

引言

引用是C++的特性,指针是C语言的特性

关于这两种特性的运行效率,人云亦云,好多人都说引用传递效率更高

以至于一些面试官在自己都不清楚的前提下面试别人

笔者有幸遇到过,由于看过底层汇编,在面试官对我说引用效率更高的时候,导致我一度怀疑自己的记忆力

下面我们就看看引用在汇编层面与指针有什么区别吧

DEMO(main.cpp)

#include

#include

void t1(int &b)

{

++b;

return;

}

void t2(int *c)

{

++*c;

return;

}

int main()

{

int a = 100;

t1(a);

t2(&a);

return 0;

}

编译

g++ -g -o test ./main.cpp

反编译

objdump -S ./test > ./test.S

AT&T(test.S)

由于是c++代码,所以汇编文件比较大

为了方便阅读,此处仅摘抄重点部分

00000000000007aa <_Z2t1Ri>:

#include

#include

void t1(int &b)

{

7aa: 55 push %rbp

7ab: 48 89 e5 mov %rsp,%rbp

7ae: 48 89 7d f8 mov %rdi,-0x8(%rbp)

++b;

7b2: 48 8b 45 f8 mov -0x8(%rbp),%rax

7b6: 8b 00 mov (%rax),%eax

7b8: 8d 50 01 lea 0x1(%rax),%edx

7bb: 48 8b 45 f8 mov -0x8(%rbp),%rax

7bf: 89 10 mov %edx,(%rax)

return;

7c1: 90 nop

}

7c2: 5d pop %rbp

7c3: c3 retq

00000000000007c4 <_Z2t2Pi>:

void t2(int *c)

{

7c4: 55 push %rbp

7c5: 48 89 e5 mov %rsp,%rbp

7c8: 48 89 7d f8 mov %rdi,-0x8(%rbp)

++*c;

7cc: 48 8b 45 f8 mov -0x8(%rbp),%rax

7d0: 8b 00 mov (%rax),%eax

7d2: 8d 50 01 lea 0x1(%rax),%edx

7d5: 48 8b 45 f8 mov -0x8(%rbp),%rax

7d9: 89 10 mov %edx,(%rax)

return;

7db: 90 nop

}

7dc: 5d pop %rbp

7dd: c3 retq

00000000000007de

:

int main()

{

7de: 55 push %rbp

7df: 48 89 e5 mov %rsp,%rbp

7e2: 48 83 ec 10 sub $0x10,%rsp

7e6: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax

7ed: 00 00

7ef: 48 89 45 f8 mov %rax,-0x8(%rbp)

7f3: 31 c0 xor %eax,%eax

int a = 100;

7f5: c7 45 f4 64 00 00 00 movl $0x64,-0xc(%rbp)

t1(a);

7fc: 48 8d 45 f4 lea -0xc(%rbp),%rax

800: 48 89 c7 mov %rax,%rdi

803: e8 a2 ff ff ff callq 7aa <_Z2t1Ri>

t2(&a);

808: 48 8d 45 f4 lea -0xc(%rbp),%rax

80c: 48 89 c7 mov %rax,%rdi

80f: e8 b0 ff ff ff callq 7c4 <_Z2t2Pi>

return 0;

814: b8 00 00 00 00 mov $0x0,%eax

}

819: 48 8b 55 f8 mov -0x8(%rbp),%rdx

81d: 64 48 33 14 25 28 00 xor %fs:0x28,%rdx

824: 00 00

826: 74 05 je 82d

828: e8 43 fe ff ff callq 670 <__stack_chk_fail@plt>

82d: c9 leaveq

82e: c3 retq

初步结论

我们通过编译与反汇编可以看到

不论指针还是引用,所有汇编代码除了t1,t2地址的不同,可以说没有任何区别

故引用其实就是指针,不过是c++帮你解引用(加了*号)并进行了一定的语法限制

以上汇编中或许有一些我没注意到的细节,欢迎各位大佬在评论区指出

完善DEMO

#include

#include

void t1(int &b)

{

++b;

return;

}

void t2(int *c)

{

++*c;

return;

}

int main(int argc,char **argv)

{

int a = 100;

long b = 10000000000;

bool ptr = false;

if(argc > 1 && strstr(argv[1],"p")) ptr = true;

if(!ptr) while(--b) t1(a);

else while(--b) t2(&a);

return 0;

}

比对运行效率

考虑到环境因素带来的不确定性,比如cpu降频,其它进程抢占cpu等

故我此处运行了多次,其中带有参数p的是使用的指针,不带有任何参数的是使用的引用

kbin@kbin-virtual-machine:~/test$ time ./test

real 0m18.444s

user 0m18.391s

sys 0m0.036s

kbin@kbin-virtual-machine:~/test$ time ./test p

real 0m18.173s

user 0m18.141s

sys 0m0.016s

kbin@kbin-virtual-machine:~/test$ time ./test

real 0m18.424s

user 0m18.418s

sys 0m0.000s

kbin@kbin-virtual-machine:~/test$ time ./test p

real 0m18.261s

user 0m18.156s

sys 0m0.088s

kbin@kbin-virtual-machine:~/test$ time ./test

real 0m18.470s

user 0m18.429s

sys 0m0.028s

kbin@kbin-virtual-machine:~/test$ time ./test p

real 0m18.300s

user 0m18.282s

sys 0m0.008s

kbin@kbin-virtual-machine:~/test$ time ./test

real 0m18.434s

user 0m18.402s

sys 0m0.028s

kbin@kbin-virtual-machine:~/test$ time ./test p

real 0m18.283s

user 0m18.259s

sys 0m0.008s

可以看到指针甚至在效率上高于引用

当然这是由于误差导致的...

最终结论

指针与引用在运行效率上是不分伯仲的

喜欢用指针还是引用完全凭借个人喜好

指针在使用的灵活度上具有很高的优势,但如果使用过程中不注意细节,就会存在安全隐患

引用由于受到c++语法的限制,牺牲了一定的灵活性,但却大大提高了使用过程中的安全性

至于网络上说引用更具有运行效率,或许是因为指针在使用前一般会去判断非NULL吧...

posted on

2023-08-30 20:06

书生执笔画浮沉

阅读(838)

评论(0)

收藏

举报

相关推荐

奶酪和黄油的区别是什么
精选内容集

精选内容集

10-30 👁️ 478
烹煮之刑到底有多残忍?为何古代帝王常用,史官却从不敢记载