Now I have been learning about inline functions and I encountered something that really made me confused
See this class
class Nebla{
private:
int x;
public:
inline void set(int y){x=y;}
inline void print(){cout<<x<<endl;}
};
it has a private data member: int x;
And it has two public inline functions: set(int y) and print()
Now since they two functions are inline, when they are called the compiler replaces the function call with the contents of the function.
So if I do this
Nebla n;
n.set(1);
n.print();
since the two functions are inline, It should be the equivalent of this:
Nebla n;
n.x=1;
cout<<n.x<<endl;
but wait a second, x is private. Therefore, this shouldn't work.
But it does and I'm confused why it does work although normally you cant access private members from outside the class?
Can anyone explain to be why you can access private data members from outside the class but when a member function is inline it can although inline just replaces the function call with the contents of the function?
Data member protection is purely conceptual. It exists only at the compiler level. It is checked and enforced when the compiler translates the source code. Once the code is compiled, there's no difference between public and private data members anymore, i.e. there are no physical mechanisms that would enforce access control and prevent access to private data members.
Member access is enforced by the compiler in accordance with the language specification. The language specification states that class member functions (regardless of whether they are inline or not) have access to private members of the class. So the compiler allows that access. Meanwhile, other functions are prohibited such access, so the compiler complains about it.
In your example you are accessing private data member from a member function. That is allowed, so the code compiles, i.e. the compiler does not complain. What happens later in the generated machine code, after the function gets inlined, is completely irrelevant. That's all there is to it.
You misunderstand how inline works. The compiler inlines the logic of the code, not the actual text of the code.
Can anyone explain to be why you can access private data members from outside the class but when a member function is inline it can although inline just replaces the function call with the contents of the function?
Because the contents of the function are the contents of the function. They don't stop being the function just because they've been inlined. You are allowed to access private member variables from inside a member function. When a member function is inlined, its code is still inside the member function because the function is inlined.
First of all, whether or not it gets inlined is up to the compiler. In a lot of cases it will decide is not the best thing to do.
Second, in the case it does inline it, it does so with a compiled binary, product of the behavior described in the C++ source code, not the actual text.
Morbo says the inline keyword doesn't work that way.
Morbo says that the inline keyword says that symbol conflict at linker time involving this function should be ignored, and that all functions whose implementation is within the declaration of the class are implicitly inline.
Morbo is wise. You should listen to Morbo, even if there is a minor technical additional meaning of inline that involves taking addresses.
More seriously, inline just let's you put definitions of the implementation into a header file. Actually making the code inline is thus easier because it doesn't have to happen at link time (and most C++ linkers are too lazy) but it does not cause the code to be inline.
And finally privacy is conceptual, it is not enforced by the C++ run time. It is just enforced at compile time by telling you that something is out of bounds.
Related
I have read, multiple times, that all member functions defined inside a class are inlined by default. Does that mean that the compiler will always put the body code of the function on the stack if it is suitable( i.e. the code does not contain any loops or function calls)?
all member functions defined inside a class are inlined by default.
No, they are inline by default.
That means that the definition can and must be provided in every translation unit where the functions are used. For member functions that means, where an instance of the class is used.
inline also has a hinting effect about machine code inlining of calls. The compiler can follow or ignore that hint at its discretion, per call.
Under What condition an inline function ceases to be an inline function and acts as any other function?
The Myth:
inline is just a suggestion which a compiler may or may not abide to. A good compiler will anyways do what needs to be done.
The Truth:
inline usually 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. 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(especially w.r.t One Definition Rule) for inline are followed.
Under What condition an inline function ceases to be an inline function and acts as any other function?
Given the quoted fact there is a deeper context to this question.
When you declare a function as static inline function, the function acts like any other static function and the keyword inline has no importance anymore, it becomes redundant.
The static keyword on the function forces the inline function to have an internal linkage.(inline functions have external linkage)
Each instance of such a function is treated as a separate function(address of each function is different) and each instance of these functions have their own copies of static local variables & string literals(an inline function has only one copy of these ).
It's at the discretion of the compiler.
But some cases just can't be inlined, like:
Recursive functions
Functions whose address is referenced somewhere
Virtual functions (there are some exceptions thought)
That depends on the compiler optimization.
Different compilers have different rules to make the code more efficient. But if you declare a function as inline, the compiler tends to respect your decision as long as none of it's rules says different.
Remember that the compiler can change completely the execution path of a method. For example, consider the next situation:
int MyClass::getValue()
{
return someVariable;
}
At compile time, there is little difference between declaring this kind of function as inline or not. Probably the compiler will make the attribute partially public and code:
myInstance->getValue()
as
myInstance->someVariable
So it's more an aesthetical decision in most cases.
From what I read somewhere long time ago, it seems that if you want class member function to be inlined during the compilation phase, the function has to be defined inside class declaration block.
But this has a downside of a detail leak. IMHO, other programmers should only see class interface when opening .h file.
Is the first statement still true in modern C++, was it ever? Is there a way to force inlining for functions that are declared, preferably in another file altogether?
Is it generally better to keep short member functions inside class declaration block, or not?
It seems that if you want class member function to be inlined during the compilation phase, the function has to be defined inside class declaration block.
That is not really true. A function that is defined inside the class definition is implicitly marked as inline. But you don't need to defined the function inside the class for it to be inline, you can explicitly request it:
struct X {
void f();
};
inline void f() {}
The inline keyword on the other hand, does not mean that the function will be inlined, but rather that it can be defined in multiple translation units, that is, if multiple translation units include the same header that contains that definition, the linker will not fail with a multiple definition error.
Now, on actual inlining, the compiler can decide to inline or not any function, regardless of whether the function is declared as inline provided that it sees the definition of that function (the code that it will inline), which is the reason why in general functions that are meant to be inlined should be defined in the header (either inside the class definition or marked inline outside.
Additionally, newer toolchains can perform whole program optimization or other link time optimizations, by which the linker can also decide that a function should be inlined. In this case, the function definition needs not be visible at the call site, so it could be defined inside the .cpp file. But if you really want the function to be inlined it is better not to depend on this feature and just define the function in the header.
Q: Is there a way to force inlining for functions?
A: No
No matter how you designate a function as inline, it is a request that
the compiler is allowed to ignore: it might inline-expand some, all,
or none of the calls to an inline function.
Q: What are the inlining rules within C++ classes?
Inline member functions in C++
As far as Standard C++ is concerned, a inline function must be defined
in every translation unit in which it is used
...
This is different from non-inline functions which must be defined only
once in an entire program (one-definition-rule)...
For member-functions, if you define your function in the class, it is
implicitly inline. And because it appears in the header, the rule that
it has to be defined in every translation unit in which it is used is
automatically satisfied.
Here is a great FAQ (one that's more "practical" than "pedantic"):
http://www.parashift.com/c++-faq-lite/inline-functions.html
Is the first statement still true in modern C++, was it ever?
As David explained, there's the inline keyword as well. It can be ignored, as Paul stated.
Is there a way to force inlining for functions that are declared,
preferably in another file altogether?
Probably by configuring your compiler. It might be doing some inling behind your back anyway. Eg. gcc has -finline-functions etc. that will be switched on for certain optimisation levels
Is it generally better to keep short member functions inside class declaration block, or no?
Up to you. Be aware though that if you have an inline method used lots of times, then you can be increasing the size of your object files, and so potentially bloat the size of what you're building and maybe slow it down.
FWIW I only tend to put implementations in header files out of laziness :)
I think my question has been asked here before, I did read them but still little confused and therefore asking to make it clear.
The C++ standard says all member functions defined inside class definition are inline
I have also heard that compiler can ignore inlining of a function. Will that be true in the above case or it will be always inlined if defined inside class definition?
Also, what was the reason behind this design, making all functions defined inside class definition inline? And what inlining has to do with source and header files?
Update: So one should always define their functions outside class if not to be inlined, right?
Update 2 by JohnB: Two functions declared inside class definition could never call each other as they would have to each contain the whole body of the other function. What will happen in this case? (Already answered by Emilio Garavaglia)
Confusion arises because inline has two effects:
It tells the compiler that the function code can be expanded where the function is called, instead of effectively being called.
It tells the compiler that the function definition can be repeated.
Point 1. is "archaic" in the sense that the compiler can in fact do what it likes in order to optimize code. It will always "inline" machine code if it can and find convenient to do and it will never do that if it cannot.
Point 2. is the actual meaning of the term: if you define (specify the body) a function in the header, since a header can be included in more sources, you must tell the compiler to inform the linker about the definition duplicates, so that they can be merged.
Now, by the language specification, free functions (not defined in class bodies) are by default not defined as inline, so defining in a header a thing like
void myfunc()
{}
if the header is included in more sources, then linked in a same output, the linker will report a multiple definition error, hence the need to define it as
inline void fn()
{}
For class members, the default is the opposite: if you just declare them, they will not be inlined. If you define them, they will be inline.
So a header should look like
//header file
class myclass
{
public:
void fn1()
{} //defined into the class, so inlined by default
void fn2();
};
inline void myclass::fn2()
{} //defined outside the class, so explicit inline is needed
And if myclass::fn2() definition goes into a proper source, must lose the inline keyword.
The inline keyword has for a function 2 meanings:
Code replacement: Wherever inline function is invoked, don't generate a function call for it but simply place the contents of the function
at the place of its call (this is something similar to macro
replacement, but type safe)
One definition rule: Don't generate multiple definition for a inline function, only generate a single definition common for all (exception: static functions)
The 1st terminology ("Code replacement"), is simply a request to the compiler. which can be ignored as compiler is better to judge whether to put the text or a function call. (for example, virtual functions or recursive functions cannot be inlined).
The 2nd terminology ("One definition rule") is guaranteed to happen by any conforming compiler. This will generate only 1 definition for all translation units. This facility eases coder's work sometimes, as for smaller function one may not want to put its definition in .cpp file (e.g. getters, setters).
Moreover, for template function which are header only constructs, this effect is mandatory. Thus template functions are inline by default.
Examples:
class A {
public:
void setMember (int i) { m_i = i; }
};
In this example mostly compiler would suffice both terminologies
class A {
inline virtual ~A () = 0;
};
A::~A() {}
Here compiler can only suffice the 2nd requirement.
The only reason to make the method function inline is if you define it in the header.
If you define a method function in a header, and you do not put inline keyword, and you include the header in several header or source files, you would get multiple definition of the method.
c++11 standard in 9.3/2 Member functions [class.mfct] tells :
A member function may be defined (8.4) in its class definition, in which case it is an inline member function (7.1.2) ...
When the definition is inside the class, it is treated as if it were declared inline, because it is assumed that class definitions live in header files that are used from more than one translation unit, so any non-inline definitions here would violate the One Definition Rule.
The compiler is, as always, free to inline whatever it thinks as long as it takes care that functions that are either explicitly or implicitly inline will not lead to linker errors. How it does that is left open by the language spec -- inlining the function of course works, but it is also acceptable to demote the symbol visibility or rename the symbol to a translation unit specific name (as if the function were in an anonymous namespace), or (as most of them do) communicate to the linker that multiple copies of that function may exist and that it should discard all but one of them.
So, in short, it is not treated any different from functions that are explicitly declared inline.
The compiler can ignore inlining if specified by the inline keyword. If the method implementation is present inside the class definition, that's a different thing, and can't be ignored. (well it can, but that makes the compiler non-conforming)
The reason behind the desing - I'm assuming a mechanism was needed where you can actually force the compiler to actually inline your functions, since the inline keyword doesn't mandate it. But in general, inline method definition is done only in cases like getter and setter methods, or some trivial 2-liners. And templates, but that's a different issue.
Inlining has to do with headers and source files in that the definition of the function must be visible to the compiler so it knows how to actually inline the call. It's more difficult to inline a function defined in an implementation file than one defined in a header.
EDIT: On a side note, the paragraph the op is reffering to is 7.1.2.3:
A function defined within a class definition is a inline function [...].
EDIT2:
Apparently, there are some difference between an inline function and inline substitution. The first is a property of a function, that doesn't only include inline substitution, the second means that the function body is actually pasted where it is called.
So the function can be inlined but not have its body pasted instead of being called.
the two things you reffer to are different aspects and not to be confused with.
1) The C++ standard says all member functions defined inside class definition are inline
2) I have also heard that compiler can ignore inlining of a function
1) is when you define the member functions inside the class declaration itself. ie: in the header files. for that you do not have to provide any keyword( ie: inline)
2) You can specify a function as inline by explicitly using the inline keyword. this is actually a request to the compiler. the compiler may or may not make the function inline according to some rules of optimization.
During a recent peer review, another Software Engineer suggested that I state that the inline function is inline in the definition (outside of the class) as well as in the declaration (inside of the class). His argument is that "By marking it inline, you are saying that this method will be executed much faster than a non-inline method, and that callers don't have to worry about excessive calls to the method."
Is that true? If I am a user of a class, do I really care about excessive calls to the method? Is there anything wrong with listing it as inline in both the definition and declaration? The C++ FAQ states:
Best practice: only in the definition outside the class body.
So who is right here?
That sounds like two totally unrelated things. Putting inline at both the declaration in the class and the definition outside of the class is not needed. Putting it at one of the declarations is enough.
If you talk about adding inline in a .cpp file where a function is defined there, and that function is a public member, then you should not do that. People who call inline functions must have their definitions visible to them. The C++ Standard requires that.
By marking it inline, you are saying that this method will be executed much faster than a non-inline method, and that callers don't have to worry about excessive calls to the method.
That's nonsense. Marking a function inline doesn't guarantee that the function will actually be physically inlined; even if it is, that's no guarantee that your function will be "faster".
By marking the definition inline as well as the declaration, you're just confusing things by pretending to your user that there's any guarantee about anything, which there isn't...
If I am a user of a class, do I really care about excessive calls to the method?
Not really.
In fact, really, the only time you should write inline is when you need to force inline storage for some reason (regardless of whether inlining occurs, using the keyword always affects the application of the one-definition rule to your function… though requiring this is rare); otherwise, let the compiler decide which functions to inline, and move on. The corollary of this is that you don't need to worry about using the keyword to pretend that it's documenting anything.
A function definition defined in the header file should use the inline specifier.
example double get_f(){return f;} defined in foo.h
should use the inline specifier as in:
inline double f_get{return f};
According to the C++ guidelineS.
As for inlining outside the header I have not seen any information that would suggest it is needed.