当前位置: 首页 > news >正文

inline小知识

在这里插入图片描述

Hello~,欢迎大家来到我的博客进行学习!

目录

  • inline
    • 为什么不能加分号?
    • 为什么要加外面的括号?
    • 为什么要加里面的括号?

inline

  • 用inline修饰的函数叫做内联函数,编译时C++编译器会在调用的地方展开内联函数,这样调用内联函数就不需要建立栈帧了,就可以提高效率。
  • inline对于编译器而言只是⼀个建议,也就是说,你加了inline编译器也可以选择在调用的地方不展开,不同编译器关于inline什么情况展开各不相同,因为C++标准没有规定这个。inline适用于频繁调用的短小函数,对于递归函数,代码相对多⼀些的函数,加上inline也会被编译器忽略。
  • C语言实现宏函数也会在预处理时替换展开,但是宏函数实现很复杂很容易出错的,且不方便调试,C++设计了inline目的就是替代C的宏函数。
  • vs编译器 debug版本下面默认是不展开inline的,这样方便调试,debug版本想展开需要设置⼀下以下两个地方。
  • inline不建议声明和定义分离到两个文件,分离会导致链接错误。因为inline被展开,就没有函数地址,链接时会出现报错。

C++弄内联函数是为了替代宏,我们在写宏的时候非常容易写错,所以C++中不太推荐宏这个东西。例如:

// 实现⼀个ADD宏函数的常⻅问题
//#define ADD(int a, int b) return a + b;
//#define ADD(a, b) a + b;
//#define ADD(a, b) (a + b)// 正确的宏实现
#define ADD(a, b) ((a) + (b))

这里有3个问题:

  • 为什么不能加分号?
  • 为什么要加外面的括号?
  • 为什么要加里面的括号?

为什么不能加分号?

首先在这个情况下,是可以加分号的:

#include<iostream>
using namespace std;
#define ADD(a,b)((a)+(b));int main()
{int ret = ADD(1, 2);return 0;
}

但是这个场景中,就不可以:

#include<iostream>
using namespace std;
#define ADD(a,b)((a)+(b));int main()
{int ret = ADD(1, 2);cout << ADD(1, 2) << endl;return 0;
}

这里我们加了分号以后,宏替换以后就会有两个分号,就会被识别为两个语句,一个分号代表一个语句,被替换后的形式为这样:

#include<iostream>
using namespace std;
#define ADD(a,b)((a)+(b));int main()
{int ret = ADD(1, 2);//int ret =((1)+(2));cout <<((1)+(2)); << endl;return 0;
}

所以不能加分号。

为什么要加外面的括号?

#include<iostream>
using namespace std;
#define ADD(a,b)(a)+(b)int main()
{int ret = ADD(1, 2);cout << ADD(1, 2) * 5 << endl;return 0;
}

这里就是运算符优先级的问题,如果不加就是11。

为什么要加里面的括号?

#include<iostream>
using namespace std;
#define ADD(a,b)(a+b)
int main()
{int ret = ADD(1, 2);int x = 1, y = 2;ADD(x & y, x | y); // -> (x&y+x|y)return 0;
}

这里也是运算符优先级的问题,这里是一种替换,传给a的不一定是变量表达式,也可能是运算表达式。这里我们本来希望&和|先运算,但是+的优先级高。

在这里我们体会到了,宏会出现各种问题所以C++推荐内联。宏的好处是快一些,因为它的本质是替换,假设我们写一个add函数,要调用是要建立栈帧的。用内联函数就不需要建立栈帧了,可以提高效率,使用内联可以避开宏的坑。

#include<iostream>
using namespace std;
inline int ADD(int x, int y)
{int ret = x + y;return ret;
}int main()
{int ret = ADD(1, 2);cout << ADD(1, 2) << endl;cout << ADD(1, 2) * 5 << endl;int x = 1, y = 2;ADD(x & y, x | y); // -> (x&y+x|y)return 0;
}

inline对于编译器而言只是⼀个建议,我们并不会用内联去写递归或一些比较长的代码,我们只会用它去写一些比较短的代码。函数被编译完之后,会变为一串指令,这里肯定会有很多很多的指令,这里和数组类似,是第一句指令的地址。

inline不建议声明和定义分离到两个文件,分离会导致链接错误。链接错误就是找不到定义就会出现。
F.h

#include <iostream>
using namespace std;
inline void f(int i);

F.cpp

#include "F.h"
void f(int i)
{cout << i << endl;
}

main.cpp

#include "F.h"
int main()
{// 链接错误:⽆法解析的外部符号 "void __cdecl f(int)" (?f@@YAXH@Z)f(1);return 0;
}

普通函数是不可以放到.h里面的,也会报链接错误。这里报错不是报错找不到,而是冲突。
F.h

#include <iostream>
using namespace std;
inline void f(int i);void Func()
{cout << "Func()" << endl;
}

加一个静态就可以解决:

#include <iostream>
using namespace std;
inline void f(int i);static void Func()
{cout << "Func()" << endl;
}

好了,我们的知识就讲到这里。如果文章内容有误,请大佬在评论区斧正!谢谢大家!
在这里插入图片描述

相关文章:

  • 深入理解Java基本类型
  • 240425 leetcode exercises
  • 常见网络安全攻击类型深度剖析(一):恶意软件攻击——病毒、蠕虫、木马的原理与防范
  • promethus基础
  • 【C/C++】从源码到执行:程序运行的完整生命周期解析
  • 风车邮箱系统详细使用指南:Windows与Ubuntu双平台解析
  • 一键设置屏幕水印 助力数据安全
  • gophish
  • 机器学习基础 - 回归模型之线性回归
  • 同一电脑下使用 python2 和 python3
  • 使用开源免费雷池WAF防火墙,接入保护你的网站
  • 100个用户的聊天系统:轮询 vs WebSocket 综合对比
  • 重生之--js原生甘特图实现
  • WordPress AI插件能自动写高质量文章吗,如何用AI提升网站流量
  • Python 3.14:探索新版本的魅力与革新
  • 7.11 Python CLI开发实战:API集成与异步处理核心技术解析
  • 人工智能在创意设计中的应用:激发无限可能
  • 【高频考点精讲】JavaScript事件循环机制:从宏任务微任务到渲染时机
  • P12167 [蓝桥杯 2025 省 C/Python A] 倒水
  • Python Transformers 库介绍
  • “70后”女博士张姿卸任国家国防科技工业局副局长
  • 韩国称DeepSeek未经同意将用户数据传至境外,外交部回应
  • 大理洱源4.8级地震致442户房屋受损,无人员伤亡
  • 人民日报:外卖平台应保障好骑手就业权益,消除后顾之忧
  • 视频丨习近平同阿塞拜疆总统会谈:两国建立全面战略伙伴关系
  • 证券时报:金价再创历史新高,“避险”黄金不应异化为投机工具