如果我们在类定义本身内部定义一个成员函数,它是否必须以内联方式处理,或者它只是它可以忽略的编译器的请求。C++中的内联函数
回答
是的,在类体内定义的函数隐含地为inline
。 (与其他声明为inline
的函数一样,这并不意味着编译器必须在函数被调用的位置执行内联扩展,它只是允许允许“单一定义规则”的放宽,并结合要求必须在使用该功能的所有翻译单元中包含定义。)
确实是内联的 - 但编译器可以忽略任何内联请求。
2003年ISO C++标准说
7.1.2/2的函数声明(8.3.5,9.3,11.4)有一个内联 指定符的内联 功能。内联说明符 指示实现 函数 在调用点处的主体的内联替换为 首选通常函数调用
机制。在调用点执行此内联
替换所需的实现不是 ;然而,即使这个内联
替换被省略,内联函数的其他 规则仍应遵守由7.1.2定义的 。7.1.2/3在类定义中定义的函数是内联函数
函数。内联说明符 不会出现在块范围函数 声明中。7.1.2/4的内联函数应每翻译单元被限定在
其被使用而在每个
情况下(3.2)具有 完全相同的定义。 [注意:在 翻译单元出现其定义之前,可能会遇到对 内联函数的调用
。 ]如果将具有外部链接的功能 在一个翻译单元中内联地声明为 ,则其 应在其中出现 的所有翻译单元的所有 中内联声明;不需要诊断。一个 内联函数与外部 连接应在 所有翻译单元中具有相同的地址。静态局部变量 extern inline
函数始终指向同一对象 。
extern内联函数中的字符串字面值与
单位中的对象相同,为 。
这是最有用的答案,但也是误导性的,一般来说,主流编译器专注于标准的“执行不需要执行这种内联替换”元素。 – marr75 2010-03-23 16:58:48
有一些不应该混为一谈两件事情:
- 你如何标记功能为是线上:在签名前使用内联定义它或者在申报点定义它;
- 编译器将如何处理这种内联标记:无论您如何将函数标记为内联,它都将被视为编译器的请求。
正如其他人所说的,一个类中定义的方法是自动请求内联的。 理解原因很有用。
假设它不是。您必须为这样的函数生成代码,并且在调用的任何地方,跳转到子例程指令都必须通过链接器引用该位置。
class A {
public:
void f() { ... your code ... }
};
每到这个代码是看到的,如果不是内联,编译器只能假设必须生成的,所以它会产生一个符号。假设它是这样的:
A__f_v:
如果该符号是全球性的,那么,如果你碰巧在不同模块中多次包括这个类的代码,你就必须在链接时乘法定义符号错误。所以它不可能是全球性的。相反,它是文件本地。
想象一下,你在多个模块中包含上述头文件。在每一个中,它都会生成该代码的本地副本。哪一个比根本不编译要好,但是当你真的只需要一个时,你会得到代码的多个副本。
这导致了下面的结论:如果你的编译器不打算内联一个函数,你最好在某处声明它,而不是要求它被内联。
不幸的是,什么是内联不是便携式的。它由编译器编写者定义。一个很好的经验法则就是在移除开销时,总是让每一行代码,特别是所有函数本身只是调用函数,内联。低于三行线性代码的东西几乎可以肯定。但是如果你在代码中有一个循环,问题是编译器是否允许它内联,更重要的是,即使按照你想要的方式,你会看到多少好处。
考虑这个内嵌代码:
inline int add(int a, int b) { return a + b; }
它不仅几乎小到原型将在源代码中,而是由内嵌代码产生的汇编语言小于调用一个子程序会。所以这个代码更小,更快。
而且,如果你碰巧经过常量:
int c= add(5,4);
它在编译时解析并没有代码。
在gcc中,我最近注意到,即使我没有内联代码,如果它是一个文件的本地代码,他们也会偷偷地内联它。只有当我在一个单独的源模块中声明函数时,它们才不会优化掉呼叫。
在光谱的另一端,假设您在1000行代码上内联请求。即使您的编译器足够愚蠢以致于无法使用它,您保存的唯一东西就是调用本身,其代价是每次调用它时,编译器都必须粘贴所有代码。如果您将该代码调用n次,您的代码会按例程* n的大小增长。因此,大于10行的任何内容几乎都不值得内联,除了仅称为非常少的特殊情况。其中一个例子可能是由另外两个人调用的私有方法。
如果您要求内联一个包含循环的方法,它只有在它经常执行少量次数时才有意义。但是考虑一个迭代一百万次的循环。即使代码被内联,在通话中花费的时间百分比也很小。因此,如果你的方法中有循环,无论如何这些方法往往会更大,但是值得从头文件中删除,因为它们a)往往会被编译器内联拒绝,b)即使它们被内联,通常不会提供任何好处
你只是想到了我。如果我以普通的方式定义一个函数(这里有一个定义和一个实现),并且我把关键字放在内部(实现?定义?)前面,那么编译器会考虑内联它?这更好?我对内联函数的主要关注点是它们很丑并且使行很长。你是说我可以让我的性感看起来很容易阅读函数内联......不仅如此,而且我应该以这种方式标记小函数?我希望你是一个活跃的用户,并回复此评论。 – Ziggy 2011-08-12 18:19:28
如果您使用原型定义了一个函数,并且在同一个标头文件中实现了内联标记,它将被内联。如果您的实现在另一个文件中,则编译器无法将其内联。这不是一个心智读者,它不知道要生成什么代码。我个人不介意在头文件中添加一些额外的代码,而不是写两次,但如果您愿意的话,您肯定可以做到这一点。 – Dov 2011-08-14 15:45:24
@ziggy如果我正确理解你的问题,是的,如果你的函数很短,那么在头文件中直接定义它可以是一个巨大的运行时速度的胜利,同时稍微减慢编译时间,并且还需要任何符号内联函数被定义。这意味着如果你的内联代码引用了其他对象,你的头文件可能需要包含其他头文件。所以在重新编译的时候会有很大的代价。但是对于一般的方法(getter/setter,用私有变量来计算某些东西),内联是一个巨大的胜利。 – Dov 2011-08-14 16:05:13
- 1. c中的内联函数
- 2. C++中的内联函数
- 3. C++内联函数
- 4. 函数在C++中的内联要求
- 5. 内嵌另一个内联函数中的函数C
- 6. C++内联函数原型
- 7. C,内联函数和GCC
- 8. C++函数指针内联
- 9. C:指针内联函数
- 10. 内联函数在其他内联函数用C
- 11. JavaScript内联函数就像在C++中
- 12. 联动的内联函数
- 13. Go中的内联函数
- 14. C++使用的typedef非内联函数
- 15. C++的内联函数范围
- 16. 内联函数
- 17. 内联函数
- 18. 内联函数
- 19. GCC内联C++函数没有“内联”关键字吗?
- 20. ASM内联调用C外部函数
- 21. C++内联函数和只在头库
- 22. 阻止C++ Builder内联函数
- 23. SQL内联函数
- 24. C++中命名空间中的内联函数
- 25. 如何根据Matlab中的另一个内联函数定义内联函数?
- 26. 在C++中,构造函数和析构函数可以是内联函数吗?
- 27. 码量的内联函数
- 28. 内联函数调用静态内联函数
- 29. 使用C#的dotNet 3.0+中的内联函数?
- 30. 内联函数中的goto语句?
另请参阅http://stackoverflow.com/questions/908830/isnt-cs-inline-totally-optional/910686#910686 – 2010-03-23 19:48:31