VC++ makes functions which are implemented within the class declaration inline functions.
If I declare a class Foo as follows, then are the CONSTRUCTOR and DESTRUCTOR inline functions?
class Foo
{
int* p;
public:
Foo() { p = new char[0x00100000]; }
~Foo() { delete [] p; }
};
{
Foo f;
(f);
}
Defining the body of the constructor INSIDE the class has the same effect as placing the function OUTSIDE the class with the "inline" keyword.
In both cases it's a hint to the compiler. An "inline" function doesn't necessarily mean the function will be inlined. That depends on the complexity of the function and other rules.
The short answer is yes. Any function can be declared inline, and putting the function body in the class definition is one way of doing that. You could also have done:
class Foo
{
int* p;
public:
Foo();
~Foo();
};
inline Foo::Foo()
{
p = new char[0x00100000];
}
inline Foo::~Foo()
{
delete [] p;
}
However, it's up to the compiler if it actually does inline the function. VC++ pretty much ignores your requests for inlining. It will only inline a function if it thinks it's a good idea. Recent versions of the compiler will also inline things that are in separate .obj files and not declared inline (e.g. from code in different .cpp files) if you use link time code generation.
You could use the __forceinline keyword to tell the compiler that you really really mean it when you say "inline this function", but it's usally not worth it. In many cases, the compiler really does know best.
Putting the function definition in the class body is equivalent to marking a function with the inline keyword. That means the function may or may not be inlined by the compiler. So I guess the best answer would be "maybe"?
To the same extent that we can make any other function inline, yes.
To inline or not is mostly decided by your compiler. Inline in the code only hints to the compiler.
One rule that you can count on is that virtual functions will never be inlined. If your base class has virtual constructor/destructor yours will probably never be inlined.
Related
Suppose we wan't to hint the compiler to inline member function where applicable.
class Base
{
public:
inline virtual f() = 0;
};
class Derived : public Base
{
public:
virtual f() override; // no inline specifier here
};
Do I need to specify inline in Derived::f() or can I omit the keyword and be sure that virtual Derived::f() is the same thing as inline Derived::f() ?
I mean is the inline keyword implicitly specified for Derived::f() or do I need to explicitly type it once again?
Do I need to specify inline in Derived::f() or can I omit the keyword and be sure that virtual Derived::f() is the same thing as inline Derived::f() ?
If you omit the inline keyword in the derived class, it is not inline in the derived class.
I mean is the inline keyword implicitly specified for Derived::f()
No, it is not.
or do I need to explicitly type it once again?
Yes, you do. However, a compiler will most likely generate code for it as though it is a non-inline member function since it is a virtual member function.
What does the inline keyword do?
Modern compilers try to balance the costs of inlining a function with the benefits.
Both the benefits and the costs are pretty clear: When a function gets inlined, there's no overhead to the function call (since there is no function call), and the compiler is able to do optimizations to the body of the function based on the context within which it's being called (since, when it's inlined, it knows that context).
Costs may include increased executable size (if it's a big function), and more instances of the assembly for the body of the function being plastered around the executable.
A rule of thumb is that if a function is big or complex, it probably won't be inlined. If it's small, it probably will be inlined.
This is good. It prevents bloated executables, but still eliminates nearly all the overhead associated with using functions. The time to execute a big, complex function oftentimes dwarfs the cost of the function call, and inlining it would have only minimal benefit.
So what does inline do? The compiler calculates how complex a function is when deciding to inline it. It then compares that calculation to some threshold. If the function is less complex than the threshold, it inlines the function.
The inline keyword basically raises the threshold for that particular function, but what it actually does under the hood varies from compiler to compiler.
Can all function calls be inlined?
If the compiler doesn't know what function is getting called, it can't inline it.
Let's look at an example:
// func_t is a pointer to a function that returns an integer
using func_t = int(*)();
int getNumber(func_t func) {
// The compiler can't inline func(), because it doesn't know
// what func *is*
return func();
}
How does this apply to virtual functions?
A virtual function call is pretty similar to invoking a function pointer, but with a few key differences. If you're invoking it from the base class, the compiler doesn't know ahead of time what function to invoke:
class Base {
virtual int getNum() { return 0; }
};
class Derived {
int value;
void setValue(int v) { value = v; }
int getNum() override { return value; }
};
int getNumFrom(Base& base) {
// The compiler doesn't know whether to call
// Base::getNum() or Derived::getNum(), so it can't inline it
return base.getNum();
}
However, if you're invoking it from a concrete instance of a class (not a reference, and not a pointer, the compiler knows exactly which version is getting called:
int getNumFromDerived() {
Derived d;
// Here, we know that we're calling Derived::getNum()
// so the compiler *can* inline it.
return d.getNum();
}
How should you apply the inline keyword?
You can specify it both in the base class, and in the derived class. Just know that it won't guarantee they get inlined, precisely because sometimes it's impossible to inline a virtual function call.
Are there alternatives?
Because templates preserve type information, the compiler always knows which function to call. It's easy to inline templated function calls, and using them won't add overhead to your program.
If possible, prefer templates over virtual inheritance.
In C++ we have feature people do not think about much, like we can execute method of a class that uses method/member that has been declared later in class i.e.:
struct s{
foo() { foo1();}
foo1() { assert(0); }
};
int main() {
s s1; s1.foo();
}
I already know that compiler puts member definitions after class definition and it can be found so the order doesn't matter: Do class functions/variables have to be declared before being used?. What I was wondering is how it would look like if we would make methods inline and compiler will respect our request and make them really inline would it work then? Would compiler do any additional stuff to reorder whole class?
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.
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.)
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.