我在文档中读到了关于内联函数的说法。我的文档说:有两种类型的内联函数:implicity function
和explicity function
。
Explicity function
:您在函数之前使用inline
关键字,并在类之外使用。例如:
inline int Math::add(int a, int b){ return a + b; }
Implicity function
:类中的每个方法都是隐含的。例如:
class Math {
int add(int a, int b) { return a + b;} // implicity inline function
};
所以,如果这是真的,那么,我不想使用inline
的每个方法,我必须在课堂外声明,对吧?如果这是真的,我可以在类中实现一个方法而不需要内联函数。
谢谢:)
答案 0 :(得分:7)
保证它不是内联的唯一方法是在编译时使其无法访问,例如,将其主体定义放入cpp文件而不是标题。
更新:一位评论者表示,即使将功能体放入不同的编译单元也无法保证有所帮助。他是绝对正确的。通常它会有所帮助,但有些编译器仍然可以内联函数。 因此,没有可靠的方法来禁用不依赖于编译器的内联。
所有内联只是一个优化问题。如果启用了适当的优化,通过编写内联关键字,您只需告诉编译器您推荐内联函数。您既不能强制编译器内联函数,也不能强制编译器不内联它。对于某些编译器,例如VC ++,有很多方法可以这样做(__declspec(noinline)
),但它们都是编译器相关的。
为什么需要禁用内联?编译器通常知道更好...如果它是出于调试目的,只需禁用优化,或者至少是函数内联。您甚至可以使用编译指示在单个文件中执行此操作。无论如何,通常应该避免调试发布版本,当然有时候无法避免它。
答案 1 :(得分:5)
从C++ standard读取,如何定义“隐式内联函数”:
可以在其类定义中定义成员函数(8.4) 在哪种情况下,它是内联成员函数(7.1.2),或者它可能是 如果已经定义,则在其类定义之外定义 声明但未在其类定义中定义。会员功能 出现在类定义之外的定义 在包含类定义的命名空间范围内。会员除外 出现在类定义之外的函数定义 除了类的成员函数的显式特化 模板和成员函数模板(14.7)出现在 类定义,成员函数不得重新声明。
编译器也不保证它真的会执行替换:
带有内联说明符的函数声明(8.3.5,9.3,11.4) 声明一个内联函数。内联说明符指示 实现内联函数体的替换 呼叫点优先于通常的函数调用机制。 执行此内联替换不需要实现 在通话点;然而,即使这种内联替换是 省略,7.1.2定义的内联函数的其他规则 仍然受到尊重。
其他所有功能都可能是“非内联”,但是一旦启用优化就会发生许多奇怪的事情,例如看看gcc
- Optimize options:
-finline-small-functions
作为O2
的一部分
当身体小于时,将功能集成到呼叫者中 预期的函数调用代码(因此程序的整体大小变小)。 编译器启发式地决定哪些函数足够简单 以这种方式值得整合。这种内联适用于所有人 函数,甚至那些没有内联声明的函数。
-finline-functions
作为O3
的一部分
考虑所有内联函数,即使它们未被声明 排队。编译器启发式地决定哪些函数值得 以这种方式集成。
如果对给定函数的所有调用都是 集成,并且函数声明为static,然后函数是 通常不会以汇编代码的形式输出。
-finline-functions-called-once
作为O1
的一部分
考虑所有调用一次的静态函数,以便内联到它们中 即使他们没有内联标记,也会调用者。如果打电话给定 函数被集成,然后该函数不作为汇编器输出 代码本身。
另一方面,您可以告诉编译器不要内联函数(-fno-inline
):
除了标有的内容之外,不要扩展任何内联函数 always_inline属性。这是未优化时的默认值 单个函数可以通过标记来免除内联 noinline属性。
答案 2 :(得分:3)
是的,类定义中的所有方法定义都是隐式inline
。
请注意,inline
并不意味着编译器实际上会在代码中内联它。如果您不希望它是内联的,只需在实现文件中分离实现。
答案 3 :(得分:2)
首先,将inline
关键字用于函数是完全合法的
在一个类中定义:
struct MyClass
{
inline int someFunctions() { return 42; }
};
此处的关键字是多余的,但并非违法。
其次,虽然inline
关键字意味着提示
编译器,它所允许的唯一正式的,必需的含义
函数的多个定义,不会导致未定义的行为
由于违反了一个定义规则。编译器确实忽略了
在某些情况下:
大多数编译器会在为调试设计的选项时忽略它 给定(或优化被关闭),并且实际上不会内联 任何东西。
最佳编译器在最大化优化时会完全忽略它 被打开;函数是否内联将取决于唯一性 关于编译器对代码和分析数据的分析,以及给定的 函数将在一个位置内联(它位于一个位置的中间) 紧密的循环),而不是另一个。 (与其他一些海报不同 已经说过,即使呼叫站点和功能定义也会发生这种情况 有两个不同的翻译单位。)
在这两个极端之间,很多编译器不做
模块间分析,至少在某种程度上
打开优化,"至少在大多数情况下接受提示"
例如,递归内联函数几乎肯定会不
如果编译器无法确定深度,则生成内联
在编译时递归。大多数编译器都无法使用
如果无法确定实际的内联生成虚函数
有局部静态分析的对象的类型,虽然有些
最好的,给定的分析器输出,揭示了一个特定的
重载将在99%的时间被调用,可能会生成if
,和
内联一个案例。
通常,您希望在头文件中尽可能少地定义,
所以对于"导出"类,你不会使用inline
(显式或隐式)
除非探查者说这是绝对必要的。对于本地课程,
在源文件中定义,无论你是谁,它都是一种风格问题
定义类定义中的函数与否(它可能或可能
关于编译器是否将它们内联 - 就像我一样没有区别
说,通常的调试选项,大多数编译器不会内联
任何东西)。