C++深度解析 内联函数分析 内联inline和宏#define(5)

C++深度解析 内联函数分析(5)

 

 

 

#define

宏定义会经过预处理器,只是进行文本替换,缺点在于不会进行语法和语义检查的,仅仅是复制、粘贴的过程,编译器根本不知道宏的存在

所以,C++中,当需要某个类型的常量时,可以使用const常量 来代替 宏常数,如:

const int A = 3   <<<-------替代------->>> #define A 3

 

 

 

内联函数 inline

使用内联函数 替代 宏代码片段

使用inline关键字声明内联函数。

内联函数没有普通函数调用的时候的额外开销(参数的入栈,函数的返回,跳转)。

内联函数会被编译器优化,编译器直接将内联函数的函数体进行扩展,扩展到调用内联函数的地方

C++编译器不一定满足函数的内联请求

示例代码一:(宏)

#include <stdio.h>

//宏代码块
#define FUNC(a, b) ((a) < (b) ? (a) : (b))

inline int func(int a, int b)
{
    return a < b ? a : b;
}

int main(int argc, char *argv[])
{
    int a = 1;
    int b = 3;
    //FUNC(++a, b)会被预处理器展开为:((++a) < (b) ? (++a) : (b))
    int c = FUNC(++a, b); //((++a) < (b) ? (++a) : (b)); 
    
    printf("a = %d\n", a);   // 3
    printf("b = %d\n", b);   // 3
    printf("c = %d\n", c);   // 3
    
    return 0;
}

结果如下:

因为FUNC是一个宏定义,文本替换。比较时候++a:a=2。如果条件成立++a:a=3。(从而a被加了两次)由此看来,使用宏定义是有副作用的。

示例代码二:(内联函数)

#include <stdio.h>

#define FUNC(a, b) ((a) < (b) ? (a) : (b))

inline int func(int a, int b)
{
    return a < b ? a : b;
}

int main(int argc, char *argv[])
{
    int a = 1;
    int b = 3;
    int c = func(++a, b);
    
    printf("a = %d\n", a); // 2
    printf("b = %d\n", b); // 3
    printf("c = %d\n", c); // 2
    
    return 0;
}

结果如下:

内联函数直接将函数体插入到调用的地方示例中,int c = func(++a, b)调用了内联函数,所以把函数体直接扩展到func(++a, b)。

 

 

 

内联函数总结:

内联函数具有普通函数的特征(参数检查,返回类型等)

函数的内联请求可能被编译器拒绝(通过配置的方式,让编译器接受内联请求)

函数被内联编译后,函数体直接扩展到调用的地方。

(宏代码片段由预处理器处理,进行简单的文本替换,没有任何编译过程,因此可能出现副作用)

因此,在C++编程中,首选内联函数,而不是宏代码片段。

 

 

 

对函数进行强制内联

g++:__attribute__((always_inline))属性,当一个函数拥有这个属性后,这个函数就会被g++编译器强制内联

MSVC:__forceinline

示例代码一:

#include <stdio.h>

//__forceinline  //MSVC
__attribute__((always_inline)) // g++
//inline
int add_inline(int n);

int main(int argc, char* argv[])
{
    int r = add_inline(10);
    
    printf("r = %d\n", r);
    
    return 0;
}

inline int add_inline(int n)
{
    int ret = 0;
    
    for(int i = 0; i < n; i++)
    {
        ret += i;
    }
    
    return ret;
}

 

 

 

注意:C++中inline内联编译的限制:

总的来说,函数体不能过于复杂。

  • 不能存在任何形式的循环语句
  • 不能存在过多的条件判断语句
  • 函数体不能过于庞大
  • 不能对函数进行取址操作
  • 函数内联声明必须在调用语句之前

内联函数和普通函数的区别:

  • 普通函数:每次调用前,CPU都会保存现场(入栈),调用完后还要恢复现场(出栈)等额外开销。
  • 内联函数:就会在每次调用的地方,将内联函数里的代码段“内联地”展开,所以省去了额外的开销

 

 

 

小结:

C++中可以通过inline声明内联函数

编译器直接将内联函数扩展到函数调用的地方

inline只是一种请求,编译器不一定允许这种请求

内联函数省去了函数调用时压栈跳转返回的开销

 

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值