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

这篇具有很好参考价值的文章主要介绍了关于指针与引用传递的效率问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

引言

  • 引用是C++的特性,指针是C语言的特性
  • 关于这两种特性的运行效率,人云亦云,好多人都说引用传递效率更高
  • 以至于一些面试官在自己都不清楚的前提下面试别人
  • 笔者有幸遇到过,由于看过底层汇编,在面试官对我说引用效率更高的时候,导致我一度怀疑自己的记忆力
  • 下面我们就看看引用在汇编层面与指针有什么区别吧

DEMO(main.cpp)

#include <iostream>
#include <cstring>
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 <iostream>
#include <cstring>
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 <main>:
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 <main+0x4f>
 828:	e8 43 fe ff ff       	callq  670 <__stack_chk_fail@plt>
 82d:	c9                   	leaveq 
 82e:	c3                   	retq   

初步结论

  • 我们通过编译与反汇编可以看到
  • 不论指针还是引用,所有汇编代码除了t1,t2地址的不同,可以说没有任何区别
  • 故引用其实就是指针,不过是c++帮你解引用(加了*号)并进行了一定的语法限制
  • 以上汇编中或许有一些我没注意到的细节,欢迎各位大佬在评论区指出

完善DEMO

#include <iostream>
#include <cstring>
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吧...

文章来源地址https://www.toymoban.com/news/detail-682591.html

到了这里,关于关于指针与引用传递的效率问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • java是值传递还是引用传递

    java是值传递;值传递是指在调用方法时将实际参数拷贝一份传递到方法中,这样在方法中如果对参数进行修改,将不会影响到实际参数;当传的是基本类型时,传的是值的拷贝,对拷贝变量的修改不影响原变量;当传的是引用类型时,传的是引用地址的拷贝,但是拷贝的地址

    2024年02月09日
    浏览(38)
  • Java 中的值传递和引用传递 ?

    一. 介绍 值传递: 值传递(Pass-by-Value)当我们向方法传递参数时,实际上是将该参数的值进行拷贝,并将拷贝后的值传递给方法内部。在方法内部对参数进行修改不会影响原始变量的值。 引用传递: 引用传递(Pass by reference)是指方法调用时实参(即传入方法的参数)是一

    2024年02月13日
    浏览(34)
  • Python 中的值传递 和 引用传递

    position 是一个 tensor; 下面这段代码第一行,如果在函数里面修改 position 会导致 下面的 position 也会发生变化 在第二行加上 clone 函数 之后,才可以保证执行完 第二行之后 的 position 的数值不会发生变换。

    2024年02月13日
    浏览(36)
  • Python值传递和引用传递(详细分析)

    目录 1. 形参与实参 2. Python的数据类型 3.Python变量及其赋值 3.1 不可变对象赋值 3.2 可变对象赋值 3.3 变量删除 3.4 变量赋值总结 4.Python函数的参数传递 4.1 参数传递定义 4.2 不可变对象的参数传递 4.3 可变对象的参数传递 5.总结 6 不可变与可变对象赋值对比: 6.1 单层源对象 6.

    2024年02月02日
    浏览(31)
  • 【C++】关于常引用的问题 #什么是权限放大?权限放小?隐式或强制转换居然还有这一步?...#

      🧑‍🎓 个人主页:简 料   🏆 所属专栏:C++   🏆 个人社区:越努力越幸运社区   🏆 简       介: 简料简料,简单有料~在校大学生一枚,专注C/C++/GO的干货分享,立志成为您的好帮手 ~ C/C++学习路线 (点击解锁) ❤️ C语言 ❤️ 初阶数据结构与算法 ❤️ C++ ❤️

    2024年02月06日
    浏览(35)
  • Go切片是值传递还是引用传递?

    很多人有个误区,认为涉及Go切片的参数是引用传递,或者经常听到Go切片是引用类型这种说法,今天我们就来说一下方面的问题。 什么是值传递? 将实参的值传递给形参,形参是实参的一份拷贝,实参和形参的内存地址不同。函数内对形参值内容的修改,是否会影响实参的

    2024年02月05日
    浏览(36)
  • 指针的指针 ok, 引用的引用 no ---- 理解引用折叠

           我们都知道,在C/C++中,出现指针的指针,也就是二级指针的场景是合法的,甚至可以是更多级的指针,都是ok的;但是如果出现了引用的引用,那绝对是非法操作,任何一款C/C++的编译器都很乐意为您检测出此类非法操作。既然会讨论这个问题,说明 引用的引用 这样

    2024年02月07日
    浏览(34)
  • Java 引用传递

    引用传递是 Java 中一个重要的概念,它与值传递不同,可以使得函数或方法可以修改传入的对象。本文将介绍 Java 中的引用传递,包括其定义、实现方式、与值传递的区别以及示例代码。 在 Java 中,变量可以存储基本类型的值或对象的引用。当一个对象的引用被传递给一个方

    2024年02月09日
    浏览(38)
  • 关于VS2022使用EF生成实体模型报错的问题:运行转换:System.NullReferenceException:对象引用未设置为对象的示例。

    起因: 之前版本vs2022生成EF模型一直没有问题,在更新了最新的vs2022之后,版本号17.6+,出现此问题: 正在运行转换:System.NullReferenceException:未将对象引用设置到对象的实例。 具体错误如下: 正在运行转换: System.NullReferenceException: 未将对象引用设置到对象的实例。 在 Micro

    2024年02月08日
    浏览(52)
  • C++【4】指针与引用;数组指针;指针数组

    /*     指针变量作为函数参数         函数的参数可以是指针类型,它的作用是将一个变量的地址传送到另一个函数中。         指针变量作为函数参数与变量本身作为函数参数不同,变量作函数参数传递的是具体值。         而指针作为函数参数传递的是内存的地址

    2024年02月07日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包