我知道内联是对编译器的提示或请求,用于避免函数调用开销。
那么,在什么基础上可以确定一个函数是否是内联的候选人? 在哪种情况下应该避免内联?
我知道内联是对编译器的提示或请求,用于避免函数调用开销。
那么,在什么基础上可以确定一个函数是否是内联的候选人? 在哪种情况下应该避免内联?
当前回答
我经常使用内联函数不是为了优化,而是为了使代码更具可读性。有时代码本身比注释、描述性名称等更短、更容易理解。例如:
void IncreaseCount() { freeInstancesCnt++; }
读者可以立即了解代码的完整语义。
其他回答
告诉编译器内联函数是一种优化,而最重要的优化规则是过早的优化是万恶之源。始终写清晰的代码(使用高效的算法),然后分析你的程序,只优化那些花费太长时间的函数。
如果您发现一个特定的函数非常简短,并且在一个紧凑的内部循环中被调用了数万次,那么它可能是一个很好的候选者。
不过,您可能会感到惊讶——许多c++编译器会自动为您内联小函数——而且它们可能也会忽略您的内联请求。
避免函数调用的开销只是故事的一半。
do:
使用inline代替#define 非常小的函数适合内联:更快的代码和更小的可执行文件(更多的机会留在代码缓存中) 这个函数很小,并且经常被调用
别:
large functions: leads to larger executables, which significantly impairs performance regardless of the faster execution that results from the calling overhead inline functions that are I/O bound the function is seldom used constructors and destructors: even when empty, the compiler generates code for them breaking binary compatibility when developing libraries: inline an existing function change an inline function or make an inline function non-inline: prior version of the library call the old implementation
在开发一个库的时候,为了让一个类将来可以扩展,你应该:
即使主体为空,也要添加非内联虚析构函数 使所有构造函数都是非内联的 除非类不能按值复制,否则编写复制构造函数和赋值操作符的非内联实现
记住,inline关键字是给编译器的一个提示:编译器可能决定不内联某个函数,也可能决定内联那些一开始就没有标记为内联的函数。我通常避免将函数标记为内联(可能在编写非常非常小的函数时分开)。
关于性能,明智的方法(一如既往)是分析应用程序,然后最终内联一组表示瓶颈的函数。
引用:
内联还是不内联 [9]内联函数 c++的策略/二进制兼容性问题 GotW #33:内联 内联回来的 有效的c++ -项目33:明智地使用内联
编辑:Bjarne Stroustrup, c++编程语言:
函数可以定义为内联的。例如:
inline int fac(int n)
{
return (n < 2) ? 1 : n * fac(n-1);
}
The inline specifier is a hint to the compiler that it should attempt to generate code for a call of fac() inline rather than laying down the code for the function once and then calling through the usual function call mechanism. A clever compiler can generate the constant 720 for a call fac(6). The possibility of mutually recursive inline functions, inline functions that recurse or not depending on input, etc., makes it impossible to guarantee that every call of an inline function is actually inlined. The degree of cleverness of a compiler cannot be legislated, so one compiler might generate 720, another 6 * fac(5), and yet another an un-inlined call fac(6). To make inlining possible in the absence of unusually clever compilation and linking facilities, the definition–and not just the declaration–of an inline function must be in scope (§9.2). An inline especifier does not affect the semantics of a function. In particular, an inline function still has a unique address and so has static variables (§7.1.2) of an inline function.
EDIT2: ISO-IEC 14882-1998, 7.1.2功能说明
使用内联说明符的函数声明(8.3.5,9.3,11.4)声明了一个内联函数。内联说明符向实现指示,在调用点对函数体进行内联替换将优先于通常的函数调用机制。实现不需要在调用点执行这种内联替换;然而,即使省略了这个内联替换,7.1.2中定义的内联函数的其他规则仍应遵守。
我读了一些答案,发现有些东西缺失了。
我使用的规则是不使用内联,除非我希望它是内联的。看起来很傻,现在解释一下。
编译器足够聪明,短函数总是内联的。永远不要让长函数作为内联函数,除非程序员说这样做。
我知道内联是一个提示或请求编译器
实际上,内联是编译器的一个命令,它没有选择,并且在内联关键字之后使所有代码内联。所以你永远不能使用内联关键字和编译器将设计最短的代码。
那么什么时候使用内联呢?
如果您想内联一些代码,则使用。我只知道一个例子,因为我只在一种情况下使用它。即用户认证。
例如,我有这样一个函数:
inline bool ValidUser(const std::string& username, const std::string& password)
{
//here it is quite long function
}
不管这个函数有多大,我都想把它作为内联的,因为它使我的软件更难破解。
此外,在维护大型项目时,内联方法有严重的副作用。当内联代码被更改时,所有使用它的文件将由编译器自动重建(如果它是一个好的编译器)。这可能会浪费大量的开发时间。
当内联方法被传输到源文件而不再内联时,整个项目必须重新构建(至少这是我的经验)。当方法转换为内联时也是如此。
最好的方法是分析你的程序,把那些被多次调用并消耗CPU周期的小函数标记为内联函数。这里的关键字是“小”——一旦函数调用开销与函数中花费的时间相比可以忽略不计,那么内联它们就没有意义了。
我建议的另一种用法是,如果你有一些小函数在性能关键代码中经常被调用,以至于缓存不相关,你可能也应该内联这些函数。同样,这也是侧写师应该能够告诉你的。