inline内联函数

inline内联函数

1 C++引用inline原因

#include <stdio.h>
//函数定义为inline即:内联函数
inline char* dbtest(int a) {
    return (i % 2 > 0) ? "奇" : "偶";
} 

int main()
{
   int i = 0;
   for (i=1; i < 100; i++) {
       printf("i:%d    奇偶性:%s /n", i, dbtest(i));    
   }
}

在我们的系统中可能经常会有一些场景:for循环调用一个工具处理函数或则是递归调用一些算法。我们知道调用一个任意函数都会为这个函数创建栈空间,如果频繁的调用小函数会消耗大量的栈空间,对内存造成很大的压力,甚至会导致内存枯竭。C++为了解决这个问题也就创造了内联函数,也就是inline。

上面的函数通过一个循环,然后循环的调用dbtest()函数,如果dbtest函数不声明为inline,系统会调用一百次dbtest函数,创建100次栈空间。但是这里我们将dbtest函数声明成inline函数之后,任何调用dbtest(i)的地方都换成了(i%2>0)?”奇”:”偶”,这样就避免了频繁调用函数对栈内存重复开辟所带来的消耗。

2 inline函数使用限制与建议

  • 一般情况,在函数频繁调用且函数内部代码很少的情况下使用内联。
  • inline函数虽然对内存有极大的优化,但是也不是随处可用的,我们发现inline函数有点类似于编译器把调用函数的地方改为一份函数代码的副本调用替代,而不用调用一次函数。
  • 所以,inline只适合函数体内代码简单的函数使用,不能包含复杂的结构控制语句例如while、switch,并且不能内联函数本身不能是直接递归函数。
  • inline函数也不是一定会生效,这个修饰只是对编译器的一个建议,所以最后能否真正内联,看编译器的意思,它如果认为函数不复杂,能在调用点展开,就会真正内联,并不是说声明了内联就会内联,声明内联只是一个建议而已
  • 其次,因为内联函数要在调用点展开,所以编译器必须随处可见内联函数的定义,要不然就成了非内联函数的调用了。所以,这要求每个调用了内联函数的文件都出现了该内联函数的定义。
  • 声明跟定义要一致:如果在每个文件里都实现一次该内联函数的话,那么,最好保证每个定义都是一样的,否则,将会引起未定义的行为。如果不是每个文件里的定义都一样,那么,编译器展开的是哪一个,那要看具体的编译器而定。所以,最好将内联函数定义放在头文件中

3 类中成员函数与inline

  • 定义在类中的成员函数默认都是内联的,如果在类定义时就在类内给出函数定义,那当然最好。如果在类中未给出成员函数定义,而又想内联该函数的话,那在类外定义上要加上inline,否则就认为不是内联的。
class A
{
    public:void Foo(int x, int y) {  } // 自动地成为内联函数
}
/*********************************************************/
// 头文件
class A
{
    public:
    void Foo(int x, int y);
}

// 定义文件
inline void A::Foo(int x, int y){} 

4 inline 是一种“用于实现的关键字"

  • 关键字inline 必须与函数定义体放在一起才能使函数成为内联,仅将inline 放在函数声明前面不起任何作用。
  • inline 是一种“用于实现的关键字”,而不是一种“用于声明的关键字”。
// 内联函数和声明在一起,不起作用
inline void Foo(int x, int y); // inline 仅与函数声明放在一起

void Foo(int x, int y){}
/*********************************************************/
// 内联函数和定义在一起,起作用
void Foo(int x, int y);

inline void Foo(int x, int y) {} // inline 与函数定义体放在一起

5 慎用inline

  • 不是所有的函数都要用inline,内联是以代码膨胀(复制)为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率。 如果执行函数体内代码的时间,相比于函数调用的开销较大,那么效率的收获会很少。
  • 另一方面,每一处内联函数的调用都要复制代码,将使程序的总代码量增大,消耗更多的内存空间。(节约栈区,消耗代码区)

6 构造函数&inline

  • 《Effective C++》阐述:将构造函数和析构函数声明为inline是没有什么意义的,即编译器并不真正对声明为inline的构造和析构函数进行内联操作,因为编译器会在构造和析构函数中添加额外的操作(申请/释放内存,构造/析构对象等),致使构造函数/析构函数并不像看上去的那么精简。
  • class中的函数默认是inline型的,编译器也只是有选择性的inline,将构造函数和析构函数声明为内联函数是没有什么意义的。

7 虚函数&inline

  • 如果将虚函数声明为inline,当是指向派生类的指针(多态性)调用声明为inline的虚函数时,不会内联展开。
  • 当是对象本身调用虚函数时(编译时确定),会内联展开,当然前提依然是函数并不复杂的情况下。

8 #define&inline

  • C++ 语言的函数内联机制既具备宏代码的效率,又增加了安全性,而且可以自由操作类的数据成员。
  • 所以在C++程序中,应该尽量内联函数取代宏代码。

参考链接

(20条消息) C++ inline函数_惜暮的博客-CSDN博客_inline函数

(20条消息) inline函数用法详解_lory17的博客-CSDN博客_inline函数

40、构造函数、析构函数、虚函数可否声明为内联函数 - 超人不会灰啊 - 博客园 (cnblogs.com)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值