VC驿站

 找回密码
 加入驿站

QQ登录

只需一步,快速开始

有编程疑问吗?还请到提问专区发帖提问!
搜索
查看: 269|回复: 0

[转载] 函数调用的开销

[复制链接]
51_avatar_middle
online_admins Syc 发表于 2018-3-26 00:44:57 | 显示全部楼层 |阅读模式
最近讲解《实用C++》新手入门教程,于是再次的看了下函数调用的开销,给大家转载过来一篇文章,希望对大家有帮助!

做了几个实验,简单学习了解一下函数调用的开销。

程序1—没有参数的函数调用:
  1. #include <stdio.h>
  2. void test()
  3. {
  4.     return;
  5. }
  6. int main(int argc, char *argv[])
  7. {
  8.     test();
  9.     return 0;
  10. }
复制代码


用 gcc -S 得到程序1的汇编代码:
  1.         .file   "test.c"
  2.         .text
  3. .globl test
  4.         .type   test, @function
  5. test:
  6.         pushl   %ebp
  7.         movl    %esp, %ebp
  8.         nop
  9.         popl    %ebp
  10.         ret
  11.         .size   test, .-test
  12. .globl main
  13.         .type   main, @function
  14. main:
  15.         pushl   %ebp
  16.         movl    %esp, %ebp
  17.         call    test
  18.         movl    $0, %eax
  19.         popl    %ebp
  20.         ret
  21.         .size   main, .-main
  22.         .ident  "GCC: (GNU) 4.5.1 20100924 (Red Hat 4.5.1-4)"
  23.         .section        .note.GNU-stack,"",@progbits
复制代码


从上面汇编代码可以看出,对于没有参数函数调用的开销:

1. 调用函数和返回,所以需要执行一次call/ret指令对。
2. 函数内部,需要保护现场,所以需要把%ebp push到栈中,返回前,再pop出来。
3. 构造函数运行环境,将%ebp赋值为当前的栈顶%esp。
则没有参数函数调用开销是5个指令。

程序2-带参数函数调用:
  1. #include <stdio.h>
  2. void test(int a)
  3. {
  4.         (a)++;
  5.         return;
  6. }
  7. int main(int argc, char *argv[])
  8. {
  9.         int a = 1;
  10.         test(a);
  11.         return 0;
  12. }
复制代码


用gcc -S得到程序2的汇编代码:
  1.         .file   "test.c"
  2.         .text
  3. .globl test
  4.         .type   test, @function
  5. test:
  6.         pushl   %ebp
  7.         movl    %esp, %ebp
  8.         addl    $1, 8(%ebp)
  9.         nop
  10.         popl    %ebp
  11.         ret
  12.         .size   test, .-test
  13. .globl main
  14.         .type   main, @function
  15. main:
  16.         pushl   %ebp
  17.         movl    %esp, %ebp
  18.         subl    $20, %esp
  19.         movl    $1, -4(%ebp)
  20.         movl    -4(%ebp), %eax
  21.         movl    %eax, (%esp)
  22.         call    test
  23.         movl    $0, %eax
  24.         leave
  25.         ret
  26.         .size   main, .-main
  27.         .ident  "GCC: (GNU) 4.5.1 20100924 (Red Hat 4.5.1-4)"
  28.         .section        .note.GNU-stack,"",@progbits
复制代码


相比于没有参数函数调用的开销,带参数函数调用多2个指令,用于传递参数:
  1. movl -4(%ebp), %eax
  2. movl %eax, (%ebp)
复制代码

每个参数的传递时都需要2个指令。
而如果是指针参数,则函数在使用时,还得需要2个指令。

这么看,函数调用的开销还挺大的。所以,当一个函数很小且调用频繁时,应该用宏或内联函数进行替代。
另外,虽然函数调用有开销,但除非有特殊的必要,该用函数的地方还是应该使用函数,否则会严重降低代码的可读性和可维护性。




上一篇:C++ 11中关于Lambda表达式(匿名函数)
下一篇:C++ 中 struct/class 等内存字节对齐的问题详解

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你已经在论坛发帖求助,并且从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友?可以给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

您需要登录后才可以回帖 登录 | 加入驿站 qq_login

本版积分规则

关闭

站长提醒上一条 /1 下一条

QQ
QQ在线咨询
联系电话
13591366679
手机扫一扫 关注本站精彩内容
wxqrcode

QQ|小黑屋|手机版|VC驿站 ( 辽ICP备09019393号tongdun|网站地图wx_jqr

GMT+8, 2018-10-22 19:13

Powered by Discuz! X3.4

© 2009-2018 cctry.com

快速回复 返回顶部 返回列表