鱼C论坛

 找回密码
 立即注册
查看: 3682|回复: 6

有篇文章说内联函数不进栈,是真的吗?请朋友们解答下,并用代码证明

[复制链接]
发表于 2013-5-10 02:22:19 | 显示全部楼层 |阅读模式
10鱼币
新手入门:关于C++中的内联函数(inline)   在c++中,为了解决一些频繁调用的小函数大量消耗栈空间或者是叫栈内存的问题,特别的引入了inline修饰符,表示为内联函数。

  可能说到这里,很多人还不明白什么是栈空间,其实栈空间就是指放置程序的局部数据也就是函数内数据的内存空间,在系统下,栈空间是有限的,如果频繁大量的使用就会造成因栈空间不足所造成的程序出错的问题,函数的死循环递归调用的最终结果就是导致栈内存空间枯竭。   下面我们来看一个例子:#include <iostream>  
#include <string>  
using namespace std;  
  
inline string dbtest(int a); //函数原形声明为inline即:内联函数
  
  
void main()  
{  
    for (int i=1;i<=10;i++)  
    {  
        cout << i << ":" << dbtest(i) << endl;  
    }  
    cin.get();  
  
}  
  
string dbtest(int a)//这里不用再次inline,当然加上inline也是不会出错的
{  
    return (a%2>0)?"奇":"偶";  
  
}  上面的例子就是标准的内联函数的用法,使用inline修饰带来的好处我们表面看不出来,其实在内部的工作就是在每个for循环的内部所有调用dbtest(i)的地方都换成了(i%2>0)?"奇":"偶"这样就避免了频繁调用函数对栈内存重复开辟所带来的消耗。   说到这里很多人可能会问,既然inline这么好,还不如把所谓的函数都声明成inline,嗯,这个问题是要注意的,inline的使用是有所限制的,inline只适合函数体内代码简单的函数使用,不能包含复杂的结构控制语句例如while switch,并且不能内联函数本身不能是直接递归函数(自己内部还调用自己的函数)。   说到这里我们不得不说一下在c语言中广泛被使用的#define语句,是的define的确也可以做到inline的这些工作,但是define是会产生副作用的,尤其是不同类型参数所导致的错误,由此可见inline有更强的约束性和能够让编译器检查出更多错误的特性,在c++中是不推荐使用define的。  关于内联函数的更多例子我就不一一举出了,灵活的使用也多靠学习者本身,我只在此抛砖引玉,让大家尽可能多的学习到c++中的一些新的先进的特性知识点。




最佳答案

查看完整内容

inline函数和普通函数不同,由于编译时期要作代码嵌入,所以编译时期inline 函数的定义要可见,因此要求inline 函数的定义必须出现在.h文件里(普通非static函数的定义不能出现在.h文件里)。此外如果inline请求被编译器拒绝,此时该函数将被转换为一个static函数,从而使该函数的定义也可以出现在.h文件里。但是这样一来,static函数的执行反而比普通函数来得更慢。 最后,用VC6编译的时候要显式选择允许inline,否则inline 总 ...
小甲鱼最新课程 -> https://ilovefishc.com
发表于 2013-5-10 02:22:20 | 显示全部楼层
inline函数和普通函数不同,由于编译时期要作代码嵌入,所以编译时期inline 函数的定义要可见,因此要求inline 函数的定义必须出现在.h文件里(普通非static函数的定义不能出现在.h文件里)。此外如果inline请求被编译器拒绝,此时该函数将被转换为一个static函数,从而使该函数的定义也可以出现在.h文件里。但是这样一来,static函数的执行反而比普通函数来得更慢。

最后,用VC6编译的时候要显式选择允许inline,否则inline 总是被编译器拒绝。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2013-5-10 09:30:04 | 显示全部楼层
不会说 你写了一个 inline 编译器就一定会把这个函数处理为一个内联函数
看具体情况 有时候 不会处理成内联函数
假如有处理为内联函数
那么 文章中的描述是对的 内联函数内有参数入栈出栈这些操作
内联函数做了类似于宏展开的操作

另外需要指出的是
文章中的递归函数 一般不会被处理为内联函数
作者不懂自欺欺人而已

评分

参与人数 1鱼币 +3 收起 理由
拈花小仙 + 3 感谢楼主无私奉献!非常感谢师兄

查看全部评分

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2013-5-10 09:32:55 | 显示全部楼层
另外再说一点
inline这个关键字应该和函数定义写在一起
才能领一个函数有可能被处理为内联函数

和函数声明写在一起是没效果的
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2013-5-11 01:48:56 | 显示全部楼层
看了楼上的 我也不好说什么了,学习了
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2013-5-11 08:45:14 | 显示全部楼层
本帖最后由 仰望天上的光 于 2013-5-11 08:52 编辑
  1. #include <iostream>
  2. using namespace std;

  3. template< int N >
  4. struct Fab{
  5.         enum { val=Fab<N-1>::val + Fab<N-2>::val};
  6. };

  7. template<>
  8. struct Fab<1>{ enum { val=1}; };

  9. template<>
  10. struct Fab<0>{ enum { val=1}; };

  11. int main () {
  12.         cout<<Fab<10>::val<<endl;
  13. }
复制代码
还有一种优化想法是:如果在编译时期我们能够知道所有的变量值,我门就可以将运行时期的循环以及递归时间转移到编译时期,比如一下例子就在编译器的编译时期直接求出了斐坡拉契数列的第10项。(智能在VS2003及以上版本编译运行)
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2013-6-3 18:17:04 | 显示全部楼层

强烈支持楼主ing……
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-7-28 20:38

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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