C++ 对象成员函数(非静态方法)

时间:2023-03-08 16:15:55

1、神奇的inline语法与语义

inline语义C99和C++98都有。之前在单源文件编写的时候一直没有发现问题,但是一考虑到多文件的链接,就发现矛盾了。

一些inline的原则:
1. inline 只是建议,不是写了 inline 编译器就一定会内联该函数。内联失败的原因有很多,识别方法也有不少,这里就不一一阐述。
2. 标准以及目标文件的本质就决定了真正的内联函数是不存在外部链接 external linkage 的,因此一般实现会要求要求 inline 的定义声明和使用一定要在同一个 Translation units 中,所以一般把内联函数定义写在头文件中。

我发现的矛盾出现在:如果内联失败,那就会为该函数生成一个代码段吗?这样多个文件编译生成的目标代码中,是否就会有多个相同且重复的代码段?这样链接的时候是否会出现命名冲突呢?

在我认知中的这些个矛盾是有递进的,或许应该这么写:

  1. 如果内联失败,那就会为该函数生成一个代码段吗?
  2. 这样多个文件编译生成的目标代码中,是否就会有多个相同且重复的代码段?
  3. 这样链接的时候是否会出现命名冲突呢?是否会出现代码冗余?

而我认为 1 2 的答案是肯定的,那编译器是如何避免 3 的后果呢?下面是个人的一些推测:

  1. C 角度 inline 的函数名没有外部链接, 具有像静态函数一样的性质。这就保证了内联失败时不会有命名冲突。
  2. ARM-ASM 角度 inline 的名字是 EXPORT [WEAK] ?也是解决命名冲突。
  3. 链接时的优化?去除冗余代码段?

1.5、教科书上的说法

[美] Stephen Prata “C++ Primer Plus(第6版)中文版” ISBN:9787115279460

8.1 C++ 内联函数

只是简单的在单源文件基础上的介绍,顺便对比了下内联函数和宏函数

10.2.3 实现类成员函数 2. 内联方法

定义位于类声明中的函数都将自动成为内联函数

如果愿意,也可以在类声明之外定义成员函数,并使其成为内联函数。为此,只需在类实现部分中定义函数时使用inline限定符即可

内联函数的特殊规则要求在每个使用它们的文件中都对其进行定义。确保内联定义对多文件程序中的所有文件都可用的、最简便的方法是:将内联定义放在定义类的头文件中(有些开发系统包含智能链接程序,允许将内联定义放在一个独立的实现文件)。

顺便说一句,根据改写规则(rewrite rule),在类声明中定义方法等同于用原型替换方法定义,然后在类声明的后面将定义改写为内联函数。

这里有提到其他的实现方法

15.1.2 友元成员函数

再次提及内联函数只有内部链接

I.1.2 使用inline而不是#define来定义小型函数

又一次对比了inline和宏函数

[美] Stephen Prata “C Primer Plus 第6版 中文版” ISBN:9787115390592

16.7 内联函数(C99)

其实C99和C11标准中叙述的是:“把函数变成内联函数建议尽可能快地调用该函数,其具体效果由实现定义”。

标准规定具有内部链接的函数可以成为内联函数,还规定了内联函数的定义与调用该函数的代码必须在同一个文件中。

与C++不同的是,C还允许混合使用内联函数定义和外部函数定义(具有外部链接的函数定义)

1.625、标准的说法

妈的C99/C11标准也定义的很乱!

未完待续

1.75、编译器的说法

2、和类相关

3、只有常成员函数足够吗?

¥¥¥、彩蛋

inline 的相关标准原文

写新的文章吧。

内联失败的原因

  1. 编译器没有实现
  2. 编译器判定不适合内联
  3. 不能内联(出现递归、取地、外部链接)

如何判读函数是否内联

  1. cc -g; db b inline_function, r & bt
  2. 利用包含符号表的运行时环境
  3. 查看汇编是否有调用

想写一篇关于asm+stdc+OS的编译链接文章

在草稿箱存着了个开头了

EXPORT [WEAK] 参考

某博文总结

CMSIS启动文件