This a C++ online test question. The test has been done.
class Person
{
std::string name;
public:
std::string const &getname(void) const ;
} ;
inline std::string const &Person::getname() const
{
return name;
}
A: The computer inserts the code of the function getname()
B: The computer generates a call to the function getname()
C: The default parameter values of the calling function are returned
D: All arguments of the function are placed on the memory stack
I choose A. Is it correct ?
Thanks.
The compiler may inline the function.
The compiler/linker will not complain when the function body is found in multiple compilation units, as long as the body is the same.
From the C++11 draft
§ 7.1.2\2
A function declaration (8.3.5, 9.3, 11.3) with an inline specifier
declares an inline function. The inline specifier 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 for inline functions defined by 7.1.2 shall
still be respected.
So, as for requirements, it's basically just a normal function, so option B. It might or might not have it's code inserted into the calling function, but that also applies to functions not marked inline, and thus isn't really anything to do with the inline keyword.
Related
I noticed a function declaration in my program which included inline, const and reference(&) before the function name. It is easy to follow each of the keywords separately, but can anyone explain the overall meaning when they are used together?
inline const std::string& foo()
{
}
I'm new to CPP programming. Ah, putting so many keywords doesn't make sense to me.
const std::string&
This is the return type of the function, which is a reference to a constant std::string.
inline
This means that this function may be defined multiple times, but you are sure that those definitions are identical and the linker may keep one of those definitions and discard the rest. You usually use this when placing the function definition in a header file, which is included by multiple cpp files, and would have invalidated One Definition Rule otherwise.
Because C++ is very much a free-form language where one could add any number of white-space between operators, keywords and symbols, we could write the function like this instead (with helpful comments):
inline // Hint for the compiler that it's allowed to inline the function
const std::string& // Function return type, a reference to a constant std::string
foo // Function name
() // Function arguments, none
{
// Empty body, not correct since the function is supposed to return something
}
Note that inline is only a hint that the compiler is allowed "inline" the function (basically copy-paste the generated code instead of doing an actual function call). The compiler is allowed to inline function calls anyway, and the inline keyword have some other implications in regards to linkage.
I read that having more than a line in a function will falsify "inline", if so how do i get to know when my function is inlined and vice-versa :/
inline int foo(int x, int y)
{
cout<<"foo-boo";
return (x > y)? x : y;
}
Remember, inlining is only a request to the compiler, not a command. Compiler can ignore the request for inlining. Compiler may not perform inlining in such circumstances like:
If a function contains a loop. (for, while, do-while)
If a function contains static variables.
If a function is recursive.
If a function return type is other than void, and the return statement doesn’t exist in function body.
If a function contains switch or goto statement.
inline is in no way related to the number of lines in a function1. It is just a compiler hint, which the compiler is not, by any means, obliged to follow. Whether a function is really inlined when declared inline, is implementation-defined.
From C++14 standard draft N3690, §7.1.2:
A function declaration (8.3.5, 9.3, 11.3) with an inline specifier
declares an inline function. The inline specifier 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 [...]
(Formatting mine.)
There are compiler-specific options and attributes to enable/disable inlining for all functions and do other, related stuff. Look up your compiler's documentation for further information.
1 A compiler could take the line count of a function into account when deciding on whether to inline a function or not but that's implementation-defined and not required by the standard.
One definition given for an inline function is
If a function is inline, the compiler places a copy of the code of
that function at each point where the function is called at compile
time.
Then my question is: why do we need to pass arguments to an inline function?
E.g
void main()
{
int a = 10;
print(a);
}
inline void print(int a)
{
printf("%d",a);
}
As per the above definition of inline, there should be no compile time errors, as the compiler will translate the code to something like:
void main()
{
int a = 10;
printf("%d",a);
}
Your conclusion is based on an invalid premise. Inline functions are not a macro-like facility that blindly splices the code of the function into the code of the caller. They are a request to the compiler that the function body be inlined if possible, but keeping the normal semantics of the function call/execution. In other words, assuming the code is correct, there should be no observable difference in behavior (other than processor and memory usage, of course) between an inlined and a non-inlined call.
This definition of inline function allows their usage to avoid a number of problems associated with macro, such as clashes of local variables defined in the function with the same name as those in the caller, or calls to function with side effects in the argument (e.g. print(a++) will work correctly with an inline function, but not with a macro).
As a result of this design, the example you provided is a compile-time error.
Inline functions are functions. So they are written and managed like a function.
A compiler may choose to treat these functions differently (may try harder to inline those), but the interface to the user still remains as function.
Moreover it is not guaranteed that inline request would be honored by the compiler.
If you inline a function, it must be defined in each translation unit where it is used and it doesn't give multiple definition link error whether it can be inlined or not by the compiler.
From 7.1.2 Function specifiers [dcl.fct.spec]
A function declaration (8.3.5, 9.3, 11.3) with an inline specifier
declares an inline function. The inline specifier 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 for inline functions defined by 7.1.2 shall
still be respected.
I search some related questions (such as Benefits of inline functions in C++?), but I still have questions.
If inline function is just to "provide a simple mechanism for the compiler to apply more OPTIMIZATIONS."
Then can I set every function as inline function?
If I wrongfully set a function as inline function, what would happen concerning performance?
Any threshold that tells me what size of function should not be inline function?
Use inline only to satisfy the One Definition Rule. Don't bother with inline for performance reasons.
If inline function is just to "provide a simple mechanism for the
compiler to apply more OPTIMIZATIONS."
If we're talking about the inline keyword, then this is not what inline is about. Like, at all.
All inline does is ensure that a function doesn't violate the One Definition Rule. It might also provide a hint to the compiler that the compiler should blow the code out inline, which may or may not improve speed, but the compiler is entitled to ignore that hint. And in fact in modern compilers they will ignore this hint a great deal of the time.
One of the cases where the compiler is very likely to not blow the code out inline is with big functions. That doesn't mean the function shouldn't be declared inline, however -- it all depends on how the function is declared, defined and used. But, again, it has nothing to do with performance.
Don't try to outsmart the compiler when it comes to applying optimization techniques. It's far better at making your program fast than you are.
Let's see what the Standard has to say on all of this.
7.1.2 Function specifiers
2/A function declaration (8.3.5, 9.3, 11.3) with an inline specifier
declares an inline function. The inline specifier 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 for inline functions defined by 7.1.2 shall
still be respected.
This tells us that inline is a request to the compiler to blow the code out inline, and that compilers are not required to perform that substitution. But this also tells us that regardless of the compiler performing this inline substitution, the "other rules" defined in 7.1.2 still apply.
There was a time, long ago, when the optimization techniques employed by C++ compilers were primitive relative to the compilers of today. Back in those days, it might have made sense to use inline as an optimization technique. But these days, compilers are much better at optimizing your code. The compiler applies techniques that, today, would make your code faster than inlining ever would, even if the function isn't actually inlined. (One possible example, RVO.)
So the end result of this is that while the original intent of 7.1.2/2 might have been to give the programmer a manual-optimization technique, modern compilers optimize so aggressively that this original intent is largely moot.
So all that's left for inline are those "other rules." So what are those other rules? (C++11 verbiage)
4/An inline function shall be defined in every translation unit in
which it is odr-used and shall have exactly the same definition in
every case (3.2). [ Note: A call to the inline function may be
encountered before its definition appears in the translation unit. —
end note ] If the definition of a function appears in a translation
unit before its first declaration as inline, the program is
ill-formed. If a function with external linkage is declared inline in
one translation unit, it shall be declared inline in all translation
units in which it appears; no diagnostic is required. An inline
function with external linkage shall have the same address in all
translation units. A static local variable in an extern inline
function always refers to the same object. A string literal in the
body of an extern inline function is the same object in different
translation units. [ Note: A string literal appearing in a default
argument is not in the body of an inline function merely because the
expression is used in a function call from that inline function. — end
note ] A type defined within the body of an extern inline function is
the same type in every translation unit.
Let's take a look at an example. Suppose we have this class template:
File: foo.h
#ifndef FOO_H
#define FOO_H
#include <string>
#include <sstream>
class StringBuilder
{
public:
template <typename T> inline StringBuilder& operator<<(const T& t)
{
mStream << t;
return * this;
}
operator std::string () const;
private:
std::stringstream mStream;
};
StringBuilder::operator std::string() const
{
return mStream.str();
}
#endif
If we #include this file in main.cpp and use the StringBuilder, everything's fine:
File: main.cpp
#include <iostream>
#include <string>
int main()
{
double d = 3.14;
unsigned a = 42;
std::string s = StringBuilder()
<< "d=" << d << ", a=" << a;
std::cout << s << "\n";
}
Output:
jdibling#hurricane:~/dev/hacks$ ./hacks
d=3.14, a=42
But if we want to use the StringBuilder in a second translation unit, we're going to have a problem:
File: other.cpp
#include <iostream>
#include <string>
#include "foo.h"
void DoSomethingElse()
{
unsigned long l = -12345;
long l2 = 223344;
std::string s = StringBuilder()
<< "l=" << l << ", l2=" << l2;
std::cout << s << "\n";
}
Compiler output:
ninja: Entering directory `.'
[1/3] Building CXX object CMakeFiles/hacks.dir/main.o
[2/3] Building CXX object CMakeFiles/hacks.dir/other.o
[3/3] Linking CXX executable hacks
FAILED: : && /usr/bin/g++ -Wall -std=c++11 -g CMakeFiles/hacks.dir/main.o CMakeFiles/hacks.dir/other.o -o hacks -rdynamic -lboost_regex-mt && :
CMakeFiles/hacks.dir/other.o: In function `std::operator|(std::_Ios_Openmode, std::_Ios_Openmode)':
/home/jdibling/dev/hacks/foo.h:21: multiple definition of `StringBuilder::operator std::string() const'
CMakeFiles/hacks.dir/main.o:/home/jdibling/dev/hacks/foo.h:21: first defined here
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.
StringBuilder::operator std::string() is defined twice; once in main.cpp and again in other.cpp -- which violated the One Definition Rule.
We can fix this by making the function inline:
class StringBuilder
{
public:
// [...]
inline operator std::string () const;
// ^^^^^^
private:
std::stringstream mStream;
};
Compiler output:
ninja: Entering directory `.'
[1/3] Building CXX object CMakeFiles/hacks.dir/main.o
[2/3] Building CXX object CMakeFiles/hacks.dir/other.o
[3/3] Linking CXX executable hacks
This works because now operator std::string is defined on both translation units with exactly the same definition. It has the same effect as defining the function directly in the declaraton:
class StringBuilder
{
public:
operator std::string () const
{
return mStream.str();
}
private:
std::stringstream mStream;
};
Just because you make a function inline it doesn't mean the compiler has to make it inline. An inline function is a hint to the compiler, not an order.
A compiler will use a set of metrics, such as optimization level, build type (debug or release), code size etc to determine if a function should be inlined.
The basic programming rule for inlining is the function should be of less then 10 lines;
But there is much more on how compiler sees it and what factors you should consider .
https://en.cppreference.com/w/cpp/language/inline
Then can I set every function as inline function?
If you set a really big function as inline it's fully compiler call if it will consider it as an inlining or not same is true for other small functions.
You should not worry about how the compiler optimizes the code.
Istead the advantages there are some disadvantages or declaring big functions as inline or defining them in .h to consider for inlining . For every inline function compiler tries to fit it into the compiler cache , and if the function is too big and you force inlining then there will be cache miss.
If I wrongfully set a function as inline function, what would happen concerning performance?
It's compiler call if it wants to inline it or not you can force it but,
you have __forceinline in windows to forcefully inline
for that also there is no guarantee that functions will be inlined. You can't force the compiler to inline a particular function, even with the __forceinline keyword. When compiling with /clr, the compiler won't inline a function if there are security attributes applied to the function, but use it judiciously as it fully depend on the judgement of the programmer how you want approach it.
https://learn.microsoft.com/en-us/cpp/cpp/inline-functions-cpp?view=vs-2019
Never force it , if you are not sure .
Any threshold that tells me what size of function should not be inline function?
A function larger then 10 lines a basic rule still there is much to consider.
There is by default inlining happening and compiler optimizes as per the defined rules.
The basic rule you should follow for inlining is to define small function in .h inorder to consider them for inlining . Never put large definations in .h files as they can really become an overhead for compiler .
If we assume that a compiler will paste the inline code at the point where the function is called, you would have large chunks of duplicated code.
Functionally, you may observe a negligible performance improvement, but a large increase in the size of your executable.
The primary reason to have the compiler paste the code rather than call the function is when the code in the function is smaller than or close to the overhead costs in calling the function and returning from it. A rule of thumb is a function of a few statements should be marked as inline. As others have stated, the inline keyword is a hint to the compiler, not a request.
Its ultimately complier decision to make function inline or not so if you declare function as inline its just gives a hint to compiler to make this function inline .
Will any function defined in the header file automatically be inline?
If I declare a function in a class and give the definition outside using keyword inline, will this function be inline? If it is, why this does not against the law that inline function should be given the body at declaration?
Any function defined inside a class definition is inline. Any function marked inline is also inline.
class C {
int f() { return 3; } // inline
int g();
int h();
}
inline int C::g() { return 4; } // inline
int C::h() { return 5; } // not inline
If all this code is in a header and that header is used in more than one translation unit you'll get a complaint that C::h has more than one definition. C::f and C::g are okay because they're inline. That's the primary role of inline these days: to permit defining the same function in multiple places (provided the definitions are "the same").
is it that any function defined in the header file will automatically be inline?
No, you should make any function defined outside of class body inline by hands. Otherwise, most likely you would get ODR violation (if include header in several translation units).
ISO C++11
3.2 One definition rule
1: No translation unit shall contain more than one definition of any variable, function, class type, enumeration type, or template.
[...]
4: Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; no diagnostic required. The definition can appear explicitly in the program, it can be found in the standard or a user-defined library, or (when appropriate) it is implicitly defined (see 12.1, 12.4 and 12.8). An inline function shall be defined in every translation unit in which it is odr-used.
if I declare a function in a class and give the definition outside using keyword inline, will this function be inline? If it is, why this does not against the law that inline function should be given the body at declaration?
There are several ways to do member function inline:
First, according to 7.1.2/3:
A function defined within a class definition is an inline function. The inline specifier shall not appear on a block scope function declaration.90 If the inline specifier is used in a friend declaration, that declaration shall be a definition or the function shall have previously been declared inline.
struct First
{
void first(){}
};
Second, Third and Fourth, according to 9.3/3:
An inline member function (whether static or non-static) may also be defined outside of its class definition provided either its declaration in the class definition or its definition outside of the class definition declares the function as inline. [ Note: Member functions of a class in namespace scope have external linkage. Member functions of a local class (9.8) have no linkage. See 3.5. —end note ]
struct STF
{
void second();
inline void third();
inline void fourth();
};
inline void STF::second(){}
void STF::third(){}
inline void STF::fourth(){}
inline is a "hint", insofar as the compiler doesn't have to honor it. It can make things inline that you don't mark inline and doesn't have to inline things that you mark as inline.
By that, I mean you shouldn't rely on it. Many recommend that you don't even use it as it is misleading. Most modern compilers completely ignore it.
The only practical use is to allow you to put static implementations into a header. Whether or not that is a good thing to do is arguable.