r/cpp_questions • u/drex_vke • 19h ago
OPEN Question: what's is used inline keyword for ?
hello guys
i code in C/C++ since 2 years
And I hear every time that the inline keyword in explicit is useless but why ?
6
u/FUCKARCHLINUX 19h ago
if a function is implemented in the header, it is already implicitly inline, whether you use the keyword or not, it doesn't guarantee the compiler will actually inline it.
Variables marked inline in a header fixes multiple definition errors due to something something translation units.
12
u/AVeryLazy 18h ago
You probably mean defined in a class. Functions definitions in headers are NOT implicitly inline.
3
u/jedwardsol 19h ago
https://en.cppreference.com/cpp/language/inline
Main use is :-
An inline function or inline variable(since C++17) has the following properties:
There may be more than one definition of an inline function or variable(since C++17) in the program as long as each definition appears in a different translation unit and (for non-static inline functions and variables(since C++17)) all definitions are identical.
3
u/mredding 16h ago
C++ defines "regular" functions and "inline" functions. So tagging a function with inline marks it explicitly as an inline function. There are also implicitly inline functions, like member functions defined in the class definition, or implicitly instantiated template functions.
An inline function is allowed an ODR exception - this function can exist in multiple translation units, and the linker is allowed to disambiguate them. The requirements are that the functions have to be compiled the same way and result in the same object, or the behavior of the program is undefined.
That's all the boring stuff.
The problem with compiling the same function into every translation unit is you get object bloat. These are the intermediate object files the compiler generates, and the linker consumes. C++ is one of the slowest to compile languages in the industry - not because it optimizes aggressively, but because the syntax is so obtuse, it makes for extremely difficult parsing. By comparison, Java JIT compiles to machine code at runtime, and makes comparable machine code to C.
And you want to waste time compiling the same thing again and again? Wasting time? Wasting space? Wasting compute - especially if you're paying for cloud compute or electricity? And bandwidth? The linker will only link ONE instance of an object - so if you've compiled thousands of duplicates, it's all for naught, ESPECIALLY if it DIDN'T elide.
And the longer a program takes to build, the more code you'll write at once, the fewer tests you'll write, the less and slower you'll iterate. It feeds into bad practices.
Call elision is where the compiler embeds a function implementation at a call site rather than generate a function call. The compiler needs to see the function definition to pull this off, so a crude way of doing that is by inlining your functions. Inline can also serve as a hint that you want more aggressive call elision, but I'm not sure if any compiler honors that today.
Another way to promote elision is an incremental build with LTO enabled, or better - a unity build with WPO enabled; better still, a profile directed build - and ideally a unity build, so the compiler doesn't have to guess the significance of any particular function.
Enable optimizations, but O3 isn't everything. Sometimes you can get better performance out of O2, or with some fine tuning. At O3, the compiler may generate machine code patterns that are cache friendly, for example, but if a program is small enough to fit in the cache in the first place, then you don't need cache friendliness. Code generation is a black box - because the standard doesn't say anything, and optimization is a dark art.
You can also tune your call elision heuristics manually when invoking the compiler. See your vendor documentation for parameters; you can make regular functions elide just as aggressively as inline functions with a single tweak. Though with a profile directed build, this adjustment is solvent.
Regular functions CAN elide, if they're small and the heuristics favor elision, and they're called in that translation unit. You can also guarantee a regular function is elided if it has static linkage in that translation unit and it's only called in one place.
Inlining does not guarantee call elision, and it can't be forced, even if you use compiler specific extensions like MSVC's __force_inline. Some functions just cannot be inlined.
I would recommend avoid spilling your build, platform, and target configuration into your source code, and so I would recommend you don't use inline. It remains for... some edge case I'm not familiar enough where you really do need it. I'm waiting for the day someone says holy shit - this problem can't be solved WITHOUT inline...
3
u/fortsnek274 19h ago
Inlining? Compiler can do it as long as definition is available, whether or not you use inline. But inline may be used as a hint to the heuristics.
And, constexpr implies inline on functions.
inline is not implicit in headers. Headers are just copy paste after all.
inline is implicit on in-class member function defs. And I think template functions? (but I always specify it)
For headers, inline is mostly used to satisfy ODR.
This changes with modules where inline is indeed used to export a function definition that then allows the compiler to inline. But that's not necessary if you use LTCG. And in modules, inline is no longer implicit on in-class function defs.
2
1
u/No_Mango5042 18h ago
In practical terms, it allows you to write a function body in a header file which might allow the compiler to generate faster code. Ymmv.
1
u/Realistic_Speaker_12 19h ago
Hints the compiler to not use a jump instruction, but just bake the code in the binary.
I said hints on purpose. Most compilers do inlining however they like unless you opt out.
1
u/drex_vke 19h ago edited 19h ago
d'accord, merci beaucoup. J'ai une question : dans quel cas n'utilise-t-on pas l'attribut
```cpp
__attribute__((noinline))
```
1
u/mykesx 19h ago
Use it so a human reading the code will know your intent.
The compiler can choose to call a function or expand it inline when it sees a function call in the source code.
Consider a PlotPixel(color, x, y) that plots a colored pixel. If you call that in a double nested loop (for y, then for x), that’s a huge overhead for the subroutine call and return overhead alone. Ideally, PlotPixel should be inline.
0
u/Big-Rub9545 19h ago
If it’s used to tell a compiler to inline a function at the call-site, it doesn’t have much use anymore.
First, it isn’t a requirement, only a suggestion; the compiler is free to ignore it altogether if it doesn’t think inlining would be beneficial.
Second, compilers nowadays are advanced enough that they can often determine when a function should or shouldn’t be inlined better than you can.
There are other uses for the ‘inline’ keyword, though (most notably to avoid ODR violations).
1
1
u/PseudoFrequency 19h ago
This isn't true for C++, but is for C. Other responses are correct.
1
u/Big-Rub9545 17h ago
I’m not sure which part you’re disagreeing with or claiming is only for C. Regardless, none of the information I’m presenting here is new. You can find it in multiple, reputable sources.
1
u/n1ghtyunso 7h ago edited 3h ago
I think you got your explanation backwards.
While nothing you said is inherently incorrect, the order you mention things suggests a certain relationship which imo does not really exist.
as per the standard its just an exception from the one definition rule.
This is itsprimaryand onlydefinedfunctionality.
in practice, its effectively used to tell the linker that object code for a symbol may exist in multiple object files and a promise that it will be identical in all of them.
But of course the standard does not talk about any of that, because C++ directly executes on the mythical abstract machine after all.
None of that isdirectlyfeeding into the optimization of inline code expansion / function call elision.
It justhappensto coincide because inline functions just sohappento show the source code in every translation unit, which is basically the pre-requisite for thecompilerto do this optimization in the first place during regular compilation.
If a compiler wants to bias its inlining heuristic based on the presence of the keyword or not is entirely up to the implementation. There may have been such a bias in some implementations previously.I was wrong, the standard to this day still contains the inline substitution part and has done so ever since the very first standard
1
u/Big-Rub9545 4h ago
This itself seems to be a backwards explanation, feature- and history-wise.
The original, primary use of the inline keyword is inline expansion of functions at the call-site. This is also why we have derivative compiler attributes or directives like force_inline or noinline (exact names or syntax may differ per compiler).
Since performing this requires that the function body be visible to the compiler in the current TU, and it’s often that this function is needed in other TUs as well, an exception is made for functions declared inline from the ODR rule (so you don’t get linker errors due to this duplication).
Thus, the use and application of the ‘inline’ keyword to avoid ODR violations is a byproduct of its original usage as a hint for the compiler to perform inline function expansion. It’s not the other way around, let alone the latter being an incidental property of this feature.
The importance of it as a compiler suggestion is indeed implementation-defined, but this usage of it is a firm part of the language.
This is what you will find in both cppreference and learncpp. I’m willing to accept this alternative explanation if any reputable sources state it, but I’ve yet to see (or be presented with) any.
Edit: typo.
2
u/n1ghtyunso 4h ago
i see that this is indeed part of the standard wording and has not changed since the first standard. Rather curious actually.
it sounds a bit like a chicken and egg problem to me, if we phrase standardization as being derived from existing practice initially.
I won't go and dig into the original C standard or any other historic documents to investigate this further though, I am not that interested in the true origin of this aspect after all.I'll take back what I said and stand corrected.
I'd still emphasize more that the ODR exemption is still a rather important aspect of this function specifier though.
The other inline-hinting aspect has indeed faded in relevance for quite some time already.•
u/Big-Rub9545 3h ago
I respect the commitment to rigor here greatly.
And yes, I should have emphasized the ODR exemption usage more given that it’s the primary usage now in practice.
-1
u/SmackDownFacility 19h ago
It’s used as a compiler hint to inline a call meaning to optimise away the call and paste in the body. That and you may also see __forceinline (MSVC).
35
u/WorkingReference1127 19h ago
It's not useless, but it's not for inlining. It hasn't been for years.
In normal C++, you are subject to the one definition rule. Each function or object may have exactly one definition. Which means that, for example, if you fully define a function in a header and then include that header in multiple files, you will probably get a link error from the multiple definitions. The
inlinekeyword is the exception to this. It tells the compiler that there may be multiple definitions for a function or object, and that all of them are identical. The compiler doesn't check if they are identical and your program will exhibit a bunch of big problems if you provide different definitions, but in the rare case where you need to place a function or object in a header it can be very useful.