C++ does inlining a function force its parameters to be copied? - c++

I recently decided to unclutter a header file which had a lot of definitions like so:
// api.h
template< typename T>
inline void func( T param )
{
// stuff here
}
so I thought of turning it into:
// api.h
#include "api_details.h"
template< typename T>
inline void func( T param )
{
return details::func( param );
}
// api_details.h
namespace details {
template< typename T>
inline void func( T param )
{
// stuff here
}
}
hoping that inline wouldn't add a cost to the extra copy I'm performing.
although the answers in 'C++ do inline functions prevent copying?' seem to imply that no copying takes place, this question arises:
if inlining doesn't copy the function parameters, then wouldn't the following behave badly?
inline void change_value( int i ) {
i++;
}
...
int x=5;
change_value(x);
assert(x==5);
is it just the optimizer that decides where to copy or not, or does the standard say anything about that?

if inlining doesn't copy the function parameters, then wouldn't the following behave badly?
In case if you change parameter it will be copied. And it is unrelated on function being inline or not.
is it just the optimizer that decides where to copy or not, or does the standard say anything about that?
Yes this is optimizer's task. Standard mentions only behaviour, not implementation(there some references regarding to implementation, but only few of them). And inline itself doesn't guarantee that function will be inlined, and vice versa, optimizer may inilne functions that wasn't declared as inline.
What really matters is that parameters that was passed by value will not be changed by function call. No matter declared it inline or not, and no matter it is actually being inlined or not.
Given that nowadays compilers are often much smarter on optimization that people are, inline usually means not "inline this function" but rather "this function may have multiply(but still identical!) definitions across translation units".

Related

c++ classes without .cpp file without inline functions?

I already asked a similar question but this one is a bit different
I don't want to write a .cpp file for every simple c++ class.
when I write a class definition and declaration in a single .hpp file, the linker complains about multiple definition of member functions which are not implemented inside the body of the class or defined with inline keyboard.
For example this will work but member functions will become inline :
// log.hpp file
#pragma once
#include<iostream>
class log {
private:
static int m_cnt = 0;
public:
void log();
};
inline void log::log() {
std::cout << ++m_cnt << std::endl;
}
So I use templates to get rid of linker complaints and hope that member functions will not become inline(do they ?):
// log.hpp file
#pragma once
#include<iostream>
template<typename T>
class log_t {
private:
static int m_cnt = 0;
public:
void log();
};
template<typename T>
void log_t<T>::log() {
std::cout << ++m_cnt << std::endl;
}
// some random type (int)
typedef log_t<int> log;
And then I can simply use log class in multiple .cpp files without linker complaints.
even when i use this method will member functions become inline ?
While it is in general bad practice to put everything in a single .h file, there are situations where it's more convenient to do so. Especially when defining small classes, and during prototyping phase where the code can change a lot quickly.
I really don't recommend using templates to solve the linking issue, since it's can slow down compilation and leads to confusion: it's like creating a function taking an argument when you except that argument to always have the same value. Anyway, typing inline is shorter than template<typename T> ;)
So you either have to define your methods in the class body or annotate them with inline if defined out of the body. This is equivalent, since C++ automatically adds inline to methods defined in the class body.
Your concern appears to be with the generated code, you probably wonder if the binary is going to grow too much. But everything's cool since regardless of inline annotations, the compiler looks at every function call and decides whether to inline it or generate a call. This means the same function may sometimes be inlined (if called in a loop) and sometimes be called.
Different compilers have different heuristics, but the inline keyword doesn't have a particularly strong influence on the compiler's decision. You can use things like __forceinline or __attribute__((always_inline)) to make ask more strongly to inline a function, but even then there's no guarantee all calls to the function will be inlined. On the contrary, you may be interested in __attribute__(noinline) for gcc which will (nearly) never inline the call:
inline __attribute__(noinline) void log::log() // gcc
{
std::cout << ++m_cnt << std::endl;
}
If you want to really know what's happening in your code you can use -Winline to see when inline functions are not inlined.
You can also use -Os or -Oz optimization levels to change internal compiler thresholds, so that it will do less inlining.
Related questions which may interest you : here and here.
In general, having every implementation in header files is a BAD idea, since it can lead to very long compile times for larger projects. Using templates to avoid this is not really a good idea, either, since it does not change this fact.
inline is only a hint to the compiler; it may ignore it and inline your template code or not. In short: The answer to your question does not matter. The standard/best way would be to use .cpp files for the implementation, even if you want to avoid it.

C++: Do function wrappers work with inline?

If you've enabled full optimizations in your compiler and have classes setup like this:
class A
{
void Do_A_Stuff();
};
class B
{
A a;
void Do_B_Stuff() { a.Do_A_Stuff(); }
};
class C
{
B b;
void Do_C_Stuff() { b.Do_B_Stuff(); }
};
class D
{
C c;
void Do_D_Stuff() { c.Do_C_Stuff(); }
};
Is there ever a situation where calling Do_D_Stuff() would be slower than directly calling Do_A_Stuff()? Also, would this require the inline keyword on each wrapper 'chain' or, since it is only a suggestion, could the compiler decide to optimize this without the keyword?
I realize there is a lot of information about inlining available, but I could not find any information specifically about chaining many wrappers together.
Also, would this require the inline keyword on each wrapper 'chain' or, since it is only a suggestion, could the compiler decide to optimize this without the keyword?
Yes, the compiler could decide to optimize it anyway, and it could also decide not to optimize it even if you specified the inline keyword (possibly producing a warning if the appropriate compiler options are set) - notice, that member functions defined in a class definition are implicitly marked as inline.
In general, if inlining is possible, the compiler will decide whether to inline or not based on the body of the function being called. However, inlining may not be possible at all if the function is a virtual function, or if the definition of the function is not visible to the compiler.
Provided that the conditions for inlining are satisfied and that the compiler considers it appropriate, there is no technical problem in inlining over a chain of function calls.
As a minor remark, notice that the functions in your classes should be public, otherwise they won't be accessible to your wrappers.
The functions are defined inside the class definition, so the inline keyword is implicit in this case.

Template meta programming inlining

First look at these templates.
struct INIWindows{
inline int GetInteger(){
return 100;
}
};
struct INILinux{
inline int GetInteger(){
return 120;
}
};
template <class Reader>
class SettingsManager : public Reader{
};
Edit: Addendum because it was not clear what i was doing.
int main(){
SettingsManager<INIWindows> Settings;
printf("Integer Reads %i\n",Settings.GetInteger());
system("pause");
return 0;
}
Is my understanding correct that this will result in SettingsManager having an inline function called get integer that will then be inlined properly by the compiler?
Is my understanding correct that this will result in SettingsManager having an inline function called get integer that will then be inlined properly by the compiler.
Yes, your understanding is correct. Your methods are going to be placed in the SettingsManager class, without a virtual dispatch, because the base classes (INIWindows and INILinux) do not have virtual methods.
The inline keyword is only a command for the compiler to try to inline the method - nothing else. It is free not to do it.
inline makes no sense inside a class. If you had defined the functions outside a class then it would indicate internal linkage. But in your current code does not serve any purpose whatsoever: all functions defined in a class are inline.
For the compiler, inline simply means that the name is no visible outside the compilation unit. In this regard, it’s similar to global static. Other than that, the compiler is free to perform function call inlining any way it wants.
In particular, the optimiser may choose to replace a call by the contents of a function. This is what you want, but it’s (almost completely) unrelated to the inline keyword, despite its name.
(By the way, this is unrelated to templates and template metaprogramming.)

Alias Methods and Performance Concerns

In order to improve code readability, sometimes I use "alias methods". These are basically methods that all do the same thing (at least in the base class; derived classes may do it differently) with different names, that enhance code readability for the class user depending on the context. Consider the code below for an example:
template <typename T>
class Foo {
public:
T bar() { /* Lots of stuff here */ }
inline T bar_alias1() { return this->bar(); }
inline T bar_alias2() { return this->bar(); }
};
Of course, if Foo::bar() was a small function, one would simply duplicate the code in all the alias methods. However, since the code may be relatively large, code duplication should be avoided, hence why the alias methods are declared as inline. But I know that the compiler does not guarantee that any function declared as inline would actually end up being expanded at compile time.
So my question is, am I introducing any performance overhead by creating these alias methods? In the code below:
Foo<BIG_OBJECT> foo;
BIG_OBJECT bo1 = foo.bar();
BIG_OBJECT bo2 = foo.bar_alias1();
Would calling foo.bar() be faster than calling foo.bar_alias1() assuming the object being passed is relatively large? Are there redundant copies of the object being made when Foo::bar_alias1() calls Foo::bar()?
I'm using Visual Studio 2010 as my compiler.
Assuming the aliased functions are inlined - and they should given the size.
There shouldn't be any performance overhead. The code-size won't increase either if the compiler decides to omit the function code and inline all calls to it.
(I'm referring to the inlining of bar_alias1(), bar() itself won't necessarily be inlined if it's large.)
However, this doesn't apply if the functions are virtual.
In C, I would do this more directly with preprocessor, but I'm not sure how appropriate that is in C++.

locally disable function inlining

I need to make the compiler to not inline an inlined function.
eg:
I have an inline function A.
I have a function B that calls A.
In B, A is inlined and this is perfect.
Now I have a function C that calls A many times.
In C, A is inlined, and it is not good.
Is it possible to tell the compiler to not inline A when it is called from C ?
--edit--
The first Idea is to create the function __declspec(noinline) A1 (that simply calls A) and call A1 instead of A in C.
But I wondering if there is a more elegant solution ?
note
I know that inline is only a suggestion, but in my program, I have some unlikely or error cases where the compiler inline functions but should not because in these cases I prefer function calls to reduce code size. I also noticed that the compiler is not always able to make the best choice (in the point of view of the developer)
In general, you cannot tell your compiler to inline or not inline a function. This is an internal optimization and even if you declare a function inline, the compiler may chose to not do so.
Some compilers allow you to control inlining to some extent. For instance, GCC has a function attribute noinline that prevents it from being inlined.
In your case, I'd try something like this:
inline void a() { ... }
void __attribute__((noinline)) wrap_a()
{ a(); }
void b() { a(); }
void c() { wrap_a(); }
Inlining is only a suggestion to compiler -- it is quite possible that the function won't be pasted in the second case. I would just trust the compiler and leave it as is.
I have found the following solution:
template <class F> ALWAYS_INLINE F NOINLINE( F f ) {
return f;
}
It seems that the compiler (MSVC at least) don't inline functions called like this:
NOINLINE(my_inline_function)();
I think it is similar to the "calling it through a function pointer" solution from Nick D
The most straight forward solution is to put the function code into a separate file.