简体   繁体   English

C++ 内联说明符的正确使用方法是什么?

[英]In C++ what is the correct way to use the inline specifier?

My goal is to reduce the function call overhead for some of the methods I have defined in my class .我的目标是减少我在class中定义的一些方法的 function 调用开销。 These methods are used by other methods and they are not intended to be publicly accessed.这些方法由其他方法使用,并且不打算公开访问。 I have done some research but could not put together the information I found.我做了一些研究,但无法将我找到的信息放在一起。 Is it sufficient to specify the method inline in the definition and not in the declaration?在定义中而不是在声明中指定inline方法就足够了吗? Is it a bad technique if the method is publicly accessible?如果该方法可以公开访问,这是不是一种糟糕的技术?

file.h文件.h

class Foo
{
    /* ... */
public:
    bool bar ( int par );
    void zar ( void );
    /* ... */
};

file.cpp文件.cpp

inline bool Foo::bar ( int par )
{
    /* ... */
}

void Foo::zar ( void )
{
    /* ... */

    if ( bar(10) )
    {
        /* ... */
    }

    /* ... */
}

Is the usage of inline specifier in this example a good technique?在此示例中使用inline说明符是一项好技术吗?

The code is operational but I want to understand the unforeseeable consequences.该代码是可运行的,但我想了解不可预见的后果。 Whether this is the correct usage or not.这是否是正确的用法。

inline has officially almost nothing to do with whether the function will be inlined or not. inline官方几乎与 function 是否内联无关。

Its official purpose is to allow multiple identical definitions to exist without violating the ODR (one-definition) rule.它的官方目的是允许存在多个相同的定义而不违反 ODR(单一定义)规则。 Meaning you can put the definition into a header, include it from multiple .cpp files - translation units - and the linker will not complain about multiple definitions, instead it will pick one .这意味着您可以将定义放入 header 中,从多个.cpp文件(翻译单元)中包含它,并且 linker 不会抱怨多个定义,而是会选择一个 Therefore you must ensure the definitions are identical (ie no two "unrelated" inline functions with the same name in separate .cpp files - they should have been marked static instead), otherwise good luck debugging the calls.因此,您必须确保定义相同(即在单独的.cpp文件中没有两个具有相同名称的“不相关” inline函数 - 它们应该被标记为static ),否则调试调用祝你好运。

If you want to force inlining, there is no standard tool for that, but all compilers support directives to do so eg __attribute__((always_inline)) for g++/clang.如果你想强制内联,没有标准工具,但所有编译器都支持这样做的指令,例如__attribute__((always_inline)) for g++/clang。

But if you want to rely on the compiler to use its judgement, you can help it by ensuring the definition is available at the call site.但是如果你想依靠编译器来使用它的判断,你可以通过确保定义在调用站点可用来帮助它。 This can be achived by either putting the definitions into headers or enabling link-time optimizations.这可以通过将定义放入标头或启用链接时优化来实现。 The former means to put the definition inside the class or somewhere after the class definition, in that case mark them inline .前者意味着将定义放在 class 内部或 class 定义之后的某处,在这种情况下将它们标记为inline Just note that this means that any change in the implementation will require recompilation of all translation units which include that header.请注意,这意味着实现中的任何更改都需要重新编译所有翻译单元,其中包括 header。

Is it sufficient to specify the method inline in the definition and not in the declaration?在定义中而不是在声明中指定内联方法就足够了吗? Is it a bad technique if the method is publicly accessible?如果该方法可以公开访问,这是不是一种糟糕的技术?

Not guaranteed but yes, if the compiler believes it is beneficial to inline the call, it has all the information necessary to do so.不能保证但是是的,如果编译器认为内联调用是有益的,它拥有这样做所需的所有信息。 Bad technique?技术不好? I would say that is completely orthogonal issue, caller should not care about the "calling convention".我会说这是完全正交的问题,调用者不应该关心“调用约定”。 Make methods public based on API design alone.仅根据 API 设计公开方法。

Is the usage of inline specifier in this example a good technique?在此示例中使用内联说明符是一项好技术吗?

No, it is useless to mark function inline inside a single translation unit.不,在单个翻译单元内内联标记 function 是没有用的。 Because it is not visible to other units and it is already visible to the original unit.因为它对其他单位不可见,而对原单位已经可见。 I would say that it is even dangerous to do so exactly due to my second paragraph, if someone else comes and implements inline Foo:bar in file2.cpp , the linker will silently most likely pick a single definition for all non-inlined calls but calls inside file.cpp which were inlined will call file::bar definition - as I said, good luck tracking those issues.我会说,由于我的第二段,这样做甚至是危险的,如果其他人来并在file2.cpp中实现inline Foo:bar ,则 linker 很可能会默默地为所有非内联调用选择一个定义,但是内联的file.cpp中的调用将调用file::bar定义 - 正如我所说,祝你好运跟踪这些问题。

inline is mostly a historical artifact similar to register , a recommendation to the compiler from a time when compilers were too dumb to make the call what to inline and when (1990s - early 2000s). inline主要是类似于register的历史工件,这是从编译器太愚蠢到无法调用内联内容和时间(1990 年代 - 2000 年代初)时向编译器提出的建议

From 7.1.2:从 7.1.2 开始:

The inline specifier indicates to the implementation that inline substitution of the function body at the point of call is to be preferred to the usual function call mechanism.内联说明符向实现表明在调用点内联替换 function 主体优于通常的 function 调用机制。

Nowadays, there is nearly no valid situation where you should be using it, save for some special cases of manual optimization and such.如今,除了一些手动优化等特殊情况外,几乎没有你应该使用它的有效情况。 In general, you shouldn't be using it at all.一般来说,你根本不应该使用它。

It's an optimization for execution speed over program size.这是对程序大小执行速度的优化。 Historically you would use inline for small functions to reduce the function call overhead.过去,您会对小函数使用inline来减少 function 调用开销。 People had this nasty habit of using function-like macros for that purpose and inline was supposed to put a stop to that.人们有这种使用类似函数的宏的坏习惯,而inline应该可以阻止这种情况。

For inline to work as expected, the function definition needs to be in the same translation unit (.cpp file and all headers it includes) as the caller.为了inline按预期工作,function 定义需要与调用方位于同一翻译单元(.cpp 文件及其包含的所有标头)中。 Which typically means that it needs to be placed in a header. It's not necessarily a bad ting to inline public methods, particularly simple setters/getters, but you shouldn't need to.这通常意味着它需要放在 header 中。 inline公共方法不一定是坏事,尤其是简单的 setter/getter,但您不需要这样做。


EDIT:编辑:

Note that inline should be accompanied with static to ensure that multiple definitions of the function aren't possible.请注意, inline应与static一起使用,以确保 function 的多个定义是不可能的。 This is required for the one definition rule (7.1.2):这是一个定义规则(7.1.2) 所必需的:

An implementation is not required to perform this inline substitution at the point of call;不需要实现在调用点执行此内联替换; however, even if this inline substitution is omitted, the other rules for inline functions defined by 7.1.2 shall still be respected.然而,即使省略了该内联替换,仍应遵守 7.1.2 定义的内联函数的其他规则。

An inline function shall be defined in every translation unit in which it is odr-used and shall have exactly the same definition in every case内联 function 应在每个使用 odr 的翻译单元中定义,并且在每种情况下都应具有完全相同的定义

An inline function shall be defined in every translation unit in which it is odr-used.内联 function 应在每个使用 odr 的翻译单元中定义。

(Similarly in C, if you declare an inline function without static and don't define the function in the same translation unit, you invoke undefined behavior (6.7.4/7).) (与 C 类似,如果您在没有 static 的情况下声明inline static并且不在同一翻译单元中定义 function,则会调用未定义的行为 (6.7.4/7)。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在 C/C++ 中声明和使用 FILE * 指针的正确方法是什么? - What is the correct way to declare and use a FILE * pointer in C/C++? 在C ++中使用移动语义的正确方法是什么? - What is the correct way to use move semantics in C++? 在C ++中分配和使用无类型内存块的正确方法是什么? - What is the correct way to allocate and use an untyped memory block in C++? 在C ++中使用const的正确方法是什么? - What's the correct way to use const in C++? 在 C++ 中为变量的异或运算实现内联汇编器的正确方法 - Correct way to implement inline assembler in c++ for xor operations on variables 在 C++ 中初始化变量的正确方法是什么 - What is the correct way to initialize a variable in C++ 格式说明符C ++有什么问题 - What is the problem with the format specifier C++ 与c ++`override` /`final`说明符相反的是什么? - What is the opposite of c++ `override` / `final` specifier? C++ 中如何使用内联说明符来保留一个定义规则? - How is the inline specifier used in C++ to preserve the one definition rule? 这是在C ++中使用for循环的正确方法吗? - Is it the correct way to use for loop in C++?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM