C ++ those details-the inline keyword

Source: Internet
Author: User

C ++ those details-the inline keyword
I. Introduction inline is a good thing, but be careful not to use it in disorder. Many macro definitions related to inline, such as _ forceinline and _ inline, have been seen in the project. Therefore, I decided to summarize the knowledge about inline when I had an obsessive-compulsive disorder. It mainly involves inline functions, usage, and forceinline. Whether the virtual function in the class will be inline or not.
Ii. inline keywords
1. Advantages of inline: inline is the keyword provided in standard C ++. Using this keyword tells the compiler that a function is an inline function. What about inline functions? Simply put, the function content is directly replaced with the called position. In this way, the performance loss of calling functions can be greatly reduced. From the source code layer, inline functions have a function structure, but are not functional after compilation. When using inline functions, there is no performance loss for function calls. However, we can check related types like functions, and we can treat inline functions as normal functions.
Let's look at an example. For example, our class has a member variable. When we use this member variable, we need to use a function to access this variable for encapsulation.

class Test{private:int m_iID;public:void SetID(int id);int GetID();};void Test::SetID(int id){m_iID = id;}int Test::GetID(){return m_iID;}
However, if we do this, we can solve the problem at once, but we need to implement it through functions. Although this is conducive to encapsulation, for a more rigorous structure, we will not bother writing. However, during running, this will cause a lot of loss to call functions. If there are thousands of calls, each call requires parameter pressure stack, saving the running status, returning results and a series of other operations. Our functions are so short, using a common function is not worth the candle. At this time, it may be the best choice to inline it. After inline, we can process it as a function during programming, and there is not much performance overhead in use. Why not?

2. inline disadvantages since inline is so good, can we use the inline function at will? Although inline can improve performance, its implementation is achieved by replacing each function call with the function itself. This will have some drawbacks. (1) program volume increase: the more function calls, the more content we insert, and the larger the code volume. If the program volume increases, additional Virtual Memory Page breaks and other behaviors will occur, reducing the hit rate of instruction cache. In this case, inline reduces the efficiency. (2) It is not conducive to dynamic upgrades. Inline functions are generally in. in the H file, you can write the Declaration and definition together. When modifying the internal content of a common function, you only need to reconnect the function. However, if the inline function is modified, all content that uses this header file must be re-compiled. (3) It is not conducive to debugging. If the implementation of the inline function is to copy the past, it is not a function during actual calling. We cannot debug an inline function. Therefore, when compiling the debug version, the compiler will not process the inline function, but as a normal function, so that we can debug it.
3. How to perform the inlineinline operation so well? Inline has two forms: explicit inline and implicit inline. Explicit inline, as its name implies, means to directly use the inline keyword and specify a function as inline. In this case, inline is usually placed outside the class. The inline keyword is not written in the function declaration, and the inline keyword is added to the function definition. For example:
class Test{private:int m_iID;public:void SetID(int id);int GetID();};inline void Test::SetID(int id){m_iID = id;}inline int Test::GetID(){return m_iID;}
However, this kind of inline seems not very common. Generally, implicit inline is used. When we put the function definition inside the class, this function will be implicitly inline, and we do not need to write any more inline keywords.
Class Test {private: int m_iID; public: // The function is defined inside the class. The implicit inlinevoid SetID (int id) {m_iID = id;} int GetID () {return m_iID ;}};
Generally, inline functions are stored in. H files, and the Declaration and definition of functions are put together. If we place the definition of a function in the class, the function will be declared as inline. Of course, this item is also effective for constructor and destructor. However, it is recommended that constructor and destructor do not use inline, which may be troublesome.
4. Will it be inline? The answer is not necessarily. The inline keyword is not the same as other keywords. It is only a request and not necessarily executed. In the end, will a function be regarded as inline or the temper of the compiler. When we write a program, we add the inline keyword before the function or directly define the function in the class. during compilation, the compiler will perform relevant analysis and check whether the function value is worthy of inline, if not, it ignores our inline request. Inline functions generally correspond to small or frequently called functions. This type of function is short, and the operation of the function itself has no high performance loss for function calling. Therefore, for the following two functions, the compiler will not inline: (1) Long functions. For example, for a function with more than 1000 rows, the compiler does not care about inline requests. If this inline is used, the program with more than 1000 rows will be inserted in all the places where the function is called, and the size of the program will be much larger. (2) contains cyclic or recursive functions. After this check, the compiler determines whether to perform inline operations on the function. However, this is not absolute. In seven cases, the compiler still does not perform inline operations on our functions. Even if we use the forceinline keyword we introduced later, we still cannot perform inline operations.


III. the _ inline and _ forceinline keywords about the _ inline and _ forceinline keywords have been seen in the project before, and they are quite entangled in their differences and relationships with inline, by the way, I will also sort it out today. 1. the _ inline keyword _ inline is relatively simple. It is a keyword provided by Microsoft compiler. It can be used in C and C ++, but only in Microsoft compiler, inline is the keyword provided by standard C ++ and can only be used in C ++, but it is not limited to the compiler. Other cases of _ inlined are the same as those of inline, so we will not repeat them here.
2. The _ forceinline keyword _ forceinline is also a keyword provided by Microsoft compiler. It can be used for C and C ++, but only for Microsoft compilers. This keyword looks awesome. Literally, translation is forced inline.
3. _ forceinline can force inline? Although it is called Force inline, whether it can be inline depends on the situation !! Obviously, it is also a request, and the compiler decides whether it can be inline. Next let's take a look at which situations cannot be inline (note __forceinline cannot be forcibly inline, and inline cannot be inline): Even with _ forceinline, the compiler cannot inline code in all circumstances. the compiler cannot inline a function if:
(1) The function or its caller is compiled with/Ob0 (the default option for debug builds ).
(2) The function and the caller use different types of exception handling (C ++ exception handling in one, structured exception handling in the other ).
(3) The function has a variable argument list.
(4) The function uses inline assembly, unless compiled with/Og,/Ox,/O1, or/O2.
(5) The function is recursive and not accompanied by # pragma inline_recursion (on ). with the pragma, recursive functions are inlined to a default depth of 16 CILS. to reduce the inlining depth, use inline_depth pragma.
(6) The function is virtual and is called virtually. Direct callto virtual functions can be inlined.
(7) The program takes the address of the function and the call is made via the pointer to the function. Direct callto functions that have had their address taken can be inlined.
(8) The function is also marked with the naked _ declspec modifier. (1) Compile a function or its caller using the/Ob0 compiler option (default option in Debug mode ). That is to say, function inline will not occur in Debug mode. (2) Functions and callers use different types of exception handling. (3) A function has variable parameters. (4) functions use online assembly (that is, the assembly language code is directly added to your C/C ++ code ). Except when the compiler is used for optimization options/Og,/Ox,/O1, or/O2. (5) The function is recursive without # inline_recursion (on ). The default depth of recursive function inline calls is 16. To reduce the inline depth, use inline_depth. (6) It is a virtual function and a virtual call. However, direct calls to virtual functions can be inline. (7) Call the function by pointing to the function pointer. (8) The function is modified by the keyword _ declspec (naked.
Well, it seems that it is still difficult to inline a function. There are so many requirements. However, in general, we only need to remember these key points: first, the function is short and concise, and the overhead of the function itself is smaller than the overhead of calling the function. Second, do not have long code, do not have loops or recursion. Third, there is no Inline when there is virtual. Fourth, no inline occurs when a function is called using a function pointer. Fifth, there is no inline under Debug.

4. I have some details about inline. Well, I have an obsessive-compulsive disorder. I decided to give a thorough explanation and summarize some special points about inline. 1. inline and virtual: first, they conflict, but no error is reported. Because inline is only a request, when both virtual and inline are available, the compiler will first satisfy virtual, and ignore our inline requests. In fact, in the class, the virtual function and inline appear quite a lot at the same time, although we may not write inline (because of implicit Inline ). The implementation of polymorphism is supported by virtual tables. All objects with virtual functions construct a virtual table at the beginning of the constructor, the first element in the virtual table is generally the object type information, and each other element stores the address of the real function. If the subclass overwrites the virtual function of the parent class, the address in the corresponding position is modified, but the position of the same function in the virtual table is the same as the subscript. When we call a virtual function using a base class pointer or reference, we only know the position of the function in a virtual table during the compilation, however, I do not know whether it is a parent-class virtual table or a sub-class virtual table. Only at runtime can I determine which virtual table is used to show polymorphism. However, if you do not use a base class pointer or reference to call a virtual function, or you are not calling a virtual function, you can directly find the address of the member function during compilation, you do not need to wait until the runtime to determine the caller's object, because the address of the function is also determined.
Although the polymorphism types represented by virtual are determined at runtime, if the caller is not a pointer or reference to the base class, the virtual address will be determined during compilation, therefore, you can use inline to expand it. Even if the base class pointer or reference is used for calling, no errors will be generated. inline will not be expanded at this time, but virtual still shows polymorphism, because inline is only recommended after all, rather than mandatory, therefore, there is no conflict between the two. In fact, after a brief analysis, we should understand that the two are indeed in conflict. Because the inline mechanism is to replace and Expand functions during compilation. This is determined before the function is run. Virtual uses dynamic binding. In short, it searches for the corresponding functions in the virtual function table based on the dynamic type at runtime. Therefore, the Inline replace during compilation will certainly not have polymorphism !! Obviously, when virtual conflicts with inline, the compiler will sacrifice performance for correctness. Inline is available only when we do not use pointers or references of base classes to call virtual functions.

2. Do not use inline constructor or inline for constructor and destructor? The answer is yes. As long as the function is defined in the class, it will be inline, And the render manager will be constructor, destructor, or even friend. However, it is best not to use inline for constructors and destructor. This is the suggestion in Objective C ++, but let's take a look at why. The constructor may have a lot of exception handling-related things that we don't see, but the compiler adds. So even if our constructor looks empty, there is nothing in it !! When the constructor inline is added and the object in the initialization list is also inline, the constructor will be huge after expansion. The same is true for destructor. In addition, there are often Xu destructor, which are also in conflict with inlne.
Therefore, it is easy to remember, and the class automatically generated by VS separates the constructor and the Destructor into the. cpp file.
3. The comparison between inline and macro is not prior to inline. It seems that we often define a macro with a simple function like this:
# Define MAX (x, y) (x)> (y )? (X): (y) int _ tmain (int argc, _ TCHAR * argv []) {int a = 3; int B = 4; cout <
 
  
This macro definition can be used to replace simple functions. However, compared with inline, this replacement is simply a dumb. First, # define is a simple replacement. There is nothing such as security type check and automatic type conversion. There are also some risks in this replacement, so we should be more careful when using macro definition. With inline, we can operate the Inline function like a common function, such as type check and automatic type conversion, and properly process the this pointer like a member function. In addition, if inline is used, the compiler performs more in-depth Optimization for us, which is also impossible for macro definition. The compiler will also analyze whether it is worth inline. If it is not worth it, it will not be inline. 4. In Debug, the inline function is not called because inline will cause the function to be copied to the called place. In fact, the Inline function is no longer a function. Therefore, most debuggers are helpless. Therefore, during debugging, the compiler chooses not to perform inline processing. That is, the debug mode is not inline. In this way, we can debug "inline functions" just like debugging common functions. 5. when using the function pointer call, although the Inline function is an inline function, sometimes if we use the function pointer to call this function, we will not perform inline processing, the compiler generates a real function entity to call the function normally. So in this case, it must be an entity function, and the function will not be Inline. V. Summary
  

Inline is a good stuff, but we should use it with caution. Although Inline can remove the loss during function calling, it is at the cost of copying. Besides, putting implementations and declarations together (if not put together, multiple implementations of one inline will occur) will lead to the inline function being unable to be upgraded along with the dynamic library. If you change the inline function, this will cause all files that use the inline function to be recompiled.

As described in Objective C ++, do not set functions as inline at the beginning, except for functions that must be inline or unexperienced (such as SetValue and GetValue ). Remember the 80-20 rule. 80% of the running time of a program is 20% of the Code. Therefore, we need to find out the code that can improve program efficiency by 20%, and do everything we can to slim it down so that it is inline.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.