gcc inline

 

Inlining of functions is an optimization and it really “works” only in optimizing compilation. If you don't use -O, no function is really inline.
   
一个函数的inlining是一种优化,而它只会"work"在有优化选项的编译中。如果你
没有(在GCC中)用到-O选项,任何函数都不会被inline
When a function is both inline and static, if all calls to the function are integrated into the caller, and the function's address is never used, then the function's own assembler code is never referenced. In this case, GCC does not actually output assembler code for the function, unless you specify the option -fkeep-inline-functions. Some calls cannot be integrated for various reasons (in particular, calls that precede the function's definition cannot be integrated, and neither can recursive calls within the definition). If there is a nonintegrated call, then the function is compiled to assembler code as usual. The function must also be compiled as usual if the program refers to its address,because that can't be inlined.
    当一个函数同时是inlinestatic的,如果对这个函数的所有调用都可以直接在调用函数中展开,而且此函数的地址没有被引用(我的理解是函数指针调用),即这个函数的汇编代码没有被引用。这种情况下,GCC实际上不生成此函数的汇编代码,除非你指定-fkeep-inline-functions选项。某些条件下有些函数调用不能直接展开(比如,在函数定义之前的函数调用,再如函数定义中有递归)。如果有没有被直接展开的函数调用,此函数会按例生成汇编代码。当程序引用了此函数的地址时,这个函数也不能直接在调用中展开,因此也按例被编译。
When an inline function is not static, then the compiler must assume that there may be calls from other source files; since a global symbol can be defined only once in any program, the function must not be defined in the other source files, so the calls therein cannot be integrated. Therefore, a non-static inline function is always compiled on its own in the usual fashion.
    当一个inline函数不是static,编译器会假定它会被其它编译单元调用,因为一个全局符号在一个程序中只能定义一次,所以这个函数不会在其他编译单元中被定义,所以那里的函数调用就不能被直接展开(注:只有在定义的文件中函数调用才会展开)。因此,非staticinline函数都会按例被编译。
If you specify both inline and extern in the function definition, then the definition is used only for inlining. In no case is the function compiled on its own, not even if you refer to its address explicitly. Such an address becomes an external reference, as if you had only declared the function, and had not defined it.
    当一个函数是inlineextern的,这个函数定义只会在调用中展开,而不会被编译,即使你明确引用它的地址。这个地址会成为一个外部引用,就好像你只是声明了这个函数,却没有定义它。
This combination of inline and extern has almost the effect of a macro. The way to use it is to put a function definition in a header file with these keywords, and put another copy of the definition (lacking inline and extern) in a library file. The definition in the header file will cause most calls to the function to be inlined. If any uses of the function remain, they will refer to the single copy in the library.

    inlineextern的函数基本上和一个宏定义的作用相当。使用的方法是在头文件中用这两个关键字定义,而把另外一份相同定义却没有inlineextern关键字的copy放在库中。头文件中的定义会使大部分的函数调用直接展开。如果还存在(通常开销)函数的调用,它就会使用库中的定义。

### GCC 13.2 中 `inline` 函数的行为特性 #### 定义与基本概念 在 C 和 C++ 编程语言中,`inline` 关键字用于建议编译器将函数的定义嵌入到调用它的位置,从而减少函数调用开销并可能提高性能。然而,在现代编译器实现中(如 GCC),`inline` 更多地被视作一种优化提示而非强制指令。 对于 GCC 13.2 版本而言,`inline` 的行为遵循 C++ 标准的规定,并在此基础上提供了一些扩展功能[^1]。以下是关于 `inline` 函数的一些重要特性和使用说明: #### 行为特性 1. **链接属性** 当一个函数被标记为 `inline` 后,默认情况下它具有内部链接(internal linkage)。这意味着即使该函数在同一程序的不同翻译单元中多次定义,也不会违反 One Definition Rule (ODR)[^1]。例如: ```cpp inline void func() { // Function body } ``` 2. **编译器决策权** 尽管开发者可以显式地指定某个函数为 `inline`,但这并不意味着编译器一定会将其展开为内联形式。实际是否执行内联取决于多种因素,包括但不限于函数大小、复杂度以及上下文环境等。GCC 提供了 `-fno-inline` 参数来禁用所有非强制性的内联操作[^2]。 3. **静态局部变量支持** 如果在一个 `inline` 函数体内存在静态局部变量,则无论此函数在哪里被实例化,都只会创建一份这样的静态对象副本。这保证了跨不同文件间的一致性[^1]: ```cpp inline int counter() { static int count = 0; return ++count; // 跨多个 TU 只有一份 'count' } ``` 4. **常量表达式的兼容性增强** 自 C++11 开始引入 constexpr 支持以来,许多原本需要通过宏或者预处理器完成的任务现在都可以借助真正的函数机制来达成目的;而到了 C++17/C++20 ,随着更灵活的语言特性加入进来之后,越来越多场景下可以直接利用 inline 结合其他关键字共同作用于更加复杂的计算逻辑之中而不必担心效率损失问题 。比如下面这个例子展示了如何构建一个既高效又安全的时间戳生成方法 : ```cpp consteval auto now_ms_since_epoch(){ using namespace std::chrono ; return duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count(); } template<typename T> concept TimeStampable=T::template supports_now_v<now_ms_since_epoch>; struct Record{ explicit(TimeStampable)Record(int id):recordId{id},timestamp{now_ms_since_epoch()}{} int recordId; decltype(auto) timestamp;//decltype(auto) here acts as placeholder for non-type template parameter deduction [^1] }; ``` 5. **调试友好型改进措施** 鉴于过度依赖传统意义上的纯粹 Inline 往往会给后续维护工作造成困扰 ,因此新版 Gcc 增加了几项辅助工具帮助开发人员更好地掌控整个过程 :一方面可以通过设置特定标志位(-finstrument-functions )记录每次进入/退出某段代码片段时的相关信息以便追踪 ;另一方面则允许用户自定义规则控制哪些部分应该优先考虑成为候选目标 (-finline-limit=N ). --- ### 示例代码展示 以下是一个简单的示例,演示了如何正确声明和定义一个 `inline` 函数: ```cpp // Header file: utils.h #ifndef UTILS_H #define UTILS_H #include <string> namespace example { inline bool is_palindrome(const std::string& str) noexcept { size_t n = str.size(); for(size_t i=0;i<n>>1;++i){ if(str[i]!=str[n-i-1])return false;} return true;} } // end of namespace example #endif /*UTILS_H*/ ``` 上述代码片段中包含了几个值得注意的地方:首先是采用了头文件保护宏防止重复包含引发错误;其次是运用命名空间封装相关内容避免污染全局作用域范围内的名称空间结构体系架构设计原则得到体现出来的同时也兼顾到了可移植性强弱程度方面的考量因素影响下的取舍平衡点所在之处有所展现给读者朋友们参考学习借鉴之用意蕴含其中矣! ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值