跟我学C++中级篇——内联补遗

一、内联引出的问题

在将一个内联变量定义到编译单元时,然后再按正常的方式使用时,编译会报一个错误“odr-used”。ODR,One Definition Rule,单一定义规则。在C/C++程序中,变量的定义只能有一处,至于ODR的规则如何定义,这个在C++的标准文档中说明的非常清楚。大家可以去查询,有时间再总结一下一起分析。
这个问题就回到了inline的问题相关,即inline(and odr-used)变量和函数,在每个编译单元是可以存在一个定义的。这也是为什么inline的变量可以在不同的编译单元使用的原因。

二、内联的优势

在前面分析的基础上,可以进一步提出,内联对编译是一种类似于提示的机制,告诉编译器,你可以看到更多的代码和更大的范围,至于能不能优化,就看编译器的能力了。
编译器在得到更多的信息后,可以有以下几个方面的优化:
1、IPO(Interprocedural Optimization)
过程优化,这个其实非常好理解,比如for循环内的变量,在低版本的编译器中可能是一个需要手动优化的目标,但在高版本编译器会自动根据情况优化到手动指定的效果。同样对于一些运算中间过程可以进行省略而直接使用结果(常量折叠)。这就需要编译器看到的代码要相对完全,包括本文提到的inline。

2、LTO(Link Time Optimization)
链接时优化,它其实是IPO的一部分。即在链接时对相关的代码进行优化。也就是说,编译器会根据不同的编译单元编译出不同的目标文件,这些目标文件就有可能进行链接时的优化。

可能有人因此会说,既然编译器如此高大威猛,为何还需要程序员小白们费心的搞这个inline?其实非常好理解,再威猛的战士也有疏漏的时候儿,不可能面面俱到,而开发者就是给编译器一个指标或者说建议,让其知晓,此处可能可以优化。另外一个就是解决文章一开头提到的ODR的问题。

三、说明

其实在前面就提到过对虚拟函数的内联优化支持,可以肯定的说,普遍意义上讲肯定是内联无法适配虚函数。但是在一些特殊的情况下,比如下面的代码:

class A{
public:
  virtual void Test(){...}
}
class B:public A
{
public:
  virtual void Test(){...}
}
inline void Get(A &a){
  a.Test();
}
int main(){
B b;
b.Test(b);
return 0;
}

其实这种就是典型的编译完全可以明白并确定inline函数中的a具体的对象,所以,就可以进行内联的优化处理,其它的情况也是类似。编译器对代码的优化随着技术的进步在不断的推进,比如现在的AI大模型的出现,以后会不会出现完全由编译器为主,而人为设置标记为辅的编程方式,也不好说。毕竟,AI自己编程都出现了,自已编程自己编译,自己测试并部署也不是不可能,这是不是《终结者》里的天网的雏形?

四、总结

许多的技术看起来很简单,用起来也没有什么可以体察到困难的地方。比如这个inline,反正写不写以后编译器还要看自己心情来处理。但其实真正的向内部观察其原理,会发现有很多技术点在等着你去融会贯通。可以把inline的函数和变量通过汇编去深入分析一下,再查看一下它的具体的实现和优化的过程,好多细节的明白,会是开发者提升自己能力的一个重要的契机!

相关推荐

  1. C++中级——补遗

    2024-05-12 10:42:08       38 阅读
  2. C++中级——

    2024-05-12 10:42:08       29 阅读
  3. c++中级——面向切片编程

    2024-05-12 10:42:08       63 阅读
  4. C++中级——函数模板的匹配

    2024-05-12 10:42:08       58 阅读
  5. C++中级——零长度数组

    2024-05-12 10:42:08       24 阅读
  6. c++中级——再谈C++20中的协程

    2024-05-12 10:42:08       40 阅读
  7. C++中级——STL的中的删除

    2024-05-12 10:42:08       46 阅读
  8. C++中级——委托构造和继承构造

    2024-05-12 10:42:08       37 阅读
  9. C++中级——const和constexpr的使用

    2024-05-12 10:42:08       32 阅读
  10. c++高级——常见的反射框架

    2024-05-12 10:42:08       35 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-05-12 10:42:08       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-05-12 10:42:08       101 阅读
  3. 在Django里面运行非项目文件

    2024-05-12 10:42:08       82 阅读
  4. Python语言-面向对象

    2024-05-12 10:42:08       91 阅读

热门阅读

  1. oracle 递归查询(结构树)

    2024-05-12 10:42:08       27 阅读
  2. Dijkstra算法

    2024-05-12 10:42:08       37 阅读
  3. 目标检测 yolov8 pth ==> onnx

    2024-05-12 10:42:08       29 阅读
  4. mongoDB

    mongoDB

    2024-05-12 10:42:08      34 阅读
  5. 麒麟系统+飞腾处理器 qt5.9.0 编译安装教程

    2024-05-12 10:42:08       32 阅读
  6. sqlite3报错:database is locked

    2024-05-12 10:42:08       29 阅读
  7. GitLab CI/CD的原理及应用详解(四)

    2024-05-12 10:42:08       23 阅读
  8. linux系统服务器中常见故障及排查方法

    2024-05-12 10:42:08       32 阅读
  9. 【docker run --name mysql8 -d -p 3306:3306】

    2024-05-12 10:42:08       31 阅读
  10. Webpack模块联邦:微前端架构的新选择

    2024-05-12 10:42:08       30 阅读
  11. 推荐算法详解

    2024-05-12 10:42:08       23 阅读
  12. Mac安装Photoshop2024 For Macv25.7.0 ps2024中文激活版

    2024-05-12 10:42:08       35 阅读