c++ classes: different ways to write a function - c++

what's the difference between the following 3 cases:
1) in point.h:
class point
{
int x,y;
public:
int getX();
};
int point::getX() {
return this->x;
}
2) in point.h:
class point
{
int x,y;
public:
int getX()
{
return this->x;
}
};
3) in point.h:
class point
{
int x,y;
public:
int getX();
};
int point.cpp:
int point::getX() {
return this->x;
}
Note: I read that it's somehow connected to inline but not sure which one of them makes the compiler to treat int getX() and inline int getX()

Avoid this first one:
struct point
{
int x,y;
int getX();
};
int point::getX() {
return this->x;
}
If multiple source files include point.h, you will get multiple definitions of point::getX, leading to a violation of the One Definition Rule (and modern linkers will give an error message).
For the second one:
struct point
{
int x,y;
int getX()
{
return this->x;
}
};
This implicitly inlines the function. This means that the function definition may be copy-pasted everywhere it is used, instead of resolving a function call. There are a few trade offs here. On one hand, by providing definitions in headers, you can more easily distribute your library. Additionally, in some cases you may see performance improvements due to the locality of the code. On the other hand, you may actually hurt performance due to instruction cache misses (more instructions around == it won't all fit in cache). And the size of your binaries may grow as the inlined function gets copied around.
Another tradeoff is that, should you ever need to change your implementation, all clients must rebuild.
Finally, depending on the sensitivity of the function, you may be revealing trade secrets through your headers (that is, there is absolutely no hiding of your secret sauce) (note: one can always decompile your binary and reverse engineer an implementation, so putting the def in the .cpp file won't stop a determined programmer, but it keeps honest people honest).
The third one, which separates a definition into a .cpp file:
// point.h
struct point
{
int x,y;
int getX();
};
// point.cpp
int point::getX() {
return this->x;
}
This will cause a function to get exported to your library (at least for gcc. In Windows, you need to be explicit by using __declspec directives to import/export). Again, there are tradeoffs here.
Changing the implementation does not require clients to recompile; you can distribute a new library for them to link to instead (the new library is ABI-compatible if you only change the impl details in the .cpp file). However, it is more difficult to distribute your library, as your binaries now need to be built for each platform.
You may see a performance decrease due to the requirement to resolve function pointers into a library for running code. You may also see a performance increase over inlining due to the fact that your code may be friendlier to the instruction cache.
In the end, there is a lot to consider. My recommendation is to go with #3 by default unless you are writing templates. When you want to look at improving performance, you can start to measure what inlining does for you (binary size as well as runtime perf). Of course you may have other information up front that makes approach #2 or #3 better suited for the task (e.g., you have a Point class, and you know that accessing X will happen everywhere and it's a really small function, so you decide to inline it).

what's the difference between the following 3 cases
The function definition is outside of the class definition. Note that in this example you've defined a non-inline function in a header. Including this header into more than one translation unit violates the One Definition Rule. This is most likely a bug.
The function definition is inside of the class definition. In this case, the function is implicitly inline. As such, it is fine to include it into multiple translation units.
The function definition is outside of the class definition again. The function is not declared inline. This time the function is defined in a separate translation unit, thereby conforming to the ODR even if the header is included into multiple translation units.
what's the problem if both b.cpp & a.cpp includes my header file
The problem is that then both b.cpp and a.cpp will define a non-inline function. The One Definition Rule says that there must be at most one definition of any inline function. Two is more than one. Therefore doing this violates the ODR and therefore such program would be ill-formed.
I'm too much confused why it's an error to write the same function in two different cpp files?
It is an "error" because the rules of the language (explained above) say that it is an "error".
what if both want to use that function?
Then declare the function in both translation units. Only define the function in one translation unit unless you declare the function inline, in which case define the function in all translation units (where the function is used) instead. Look at the examples 2. and 3. of your question to see how that can be done.
so the code in method 1 is not automatically inlined?
No. Functions are not automatically declared inline. Function is declared inline only if A. inline keyword is used, or if B. it is a non-static member function that is defined within the class definition (or in a case involving constexpr that I shall omit here). None of those cases apply to the example 1, therefore it is not an inline function.

Related

Avoid compiling definition of inline function multiple times

I have a non-template struct in a header file:
struct X {
constexpr X() : /* ... */ { /* ... */ }
constexpr void f() {
// ...
}
};
With functions of varying size. This is used in a lot of different translation units, and each function appears in multiple object files for them to be discarded in the final executable.
What I want is for the definitions to be in a single object file, and the other translation units can either inline the function or use an external definition (something like the extern inline semantics from C). How can I do that?
It seems to work with templates and extern template:
namespace detail {
template<std::nullptr_t>
struct X_base {
constexpr X_base() // ...
constexpr void f() // ...
};
extern template struct X_base<nullptr>;
}
struct X : detail::X_base<nullptr> {
using X_base::X_base;
};
// X.cpp
#include <X.hpp>
template struct detail::X_base<nullptr>;
But are there any major downsides to this (longer symbol names, confusing to read, needs documentation, etc.), or are there any easier ways to do this?
C++ doesn’t have the notion of an inline function that must be emitted in one translation unit and which therefore certainly need not be emitted anywhere else. (It doesn’t have the notion of emitting object code at all, but the point is that there’s no syntax that says “I promise this definition is ODR-identical to the others except that it and only it bears this marker.” so that compilers could do that.)
However, the behavior you want is the obvious way of implementing C++20 modules: because the definition of an inline function in a module is known to be the only definition, it can and should be emitted once in case several importing translation units need an out-of-line copy of it. (Inlining is still possible because the definition is made available in a compiler-internal form as part of building the module.) Bear in mind that member functions defined in a class in a module are not automatically inline, although constexpr still implies it.
Another ugly workaround is to make non-inline wrappers to be used outside of constant evaluation, although this could get unwieldy if there were multiple levels of constexpr functions that might also be used at runtime.

How the Inline functions having multiple lines of code are treated as a single line?

I have an idea on defining inline functions(normal functions) globally
using "inline keyword" increases performance if the snippet is small.I have
a doubt that :
"how the member functions defined inside classes
also gives the same performance and considered as inline?"
Actually inline functions contain a single line of code
This statement is wrong. There's no such constraint.
Inline function merely means that all the function definition code is placed directly where it is declared.
but member functions defined inside a class contain multiple code instead treated as inline why?
If you're referring to the inline keyword there's also no constraint that functions marked with that keyword can only contain a single line of code.
If it's actually inlined by the compiler (i.e. assembly code directly inserted in place, without a function call) is left to its decision, and mostly depends on compiler optimization strategies chosen in the optimization flags.
You need to provide the inline keyword for non class member functions if they are completely defined in a header file to avoid ODR violation errors.
Here's an example (header file assumed):
class foo {
int x_;
public:
// Inside the class declaration 'inline' is assumed as default
int x() const { return x_; }
int y() const {
int result = 0;
// Do some complicated calculation spanning
// a load of code lines
return result;
}
};
inline int bar() { // inline is required here, otherwise the compiler
// will see multiple definitions of that function
// in every translation unit (.cpp) that includes
// that header file.
return 42;
}
Inline doesn't mean its just single line of code . It means the whole code if it is single line or multiple lines gets inserted at the function calling point thereby reducing function call overhead .
Look at this code, I know it's not C++ but basics are the same.
#include <stdio.h>
#define inlineMacro(x) ((x) = (x) + 1); ((x) = (x) * 2)
int main()
{
int i = 5;
inlineMacro(i);
printf("%i",i);
return 0;
}
Outputs:
12
You can put all of your code on single line. So don't be detracted by keyword inline, it's just for compiler.
I have got a clear explanation from all of you guys.
INTUITION in three 4 points:
1.For normal functions(not methods that are declared /defined in classes) inline keyword is used to interpolate the assembly code (by compiler),thereby avoiding repeating function calls.
2.For methods declared inside classes ,the performance would be same if they are declared as normal functions with inline keyword(no class concept) for a small snippet.
3.method declaration(for classes) is implicit inline.
4.functions declaration is (if needed) is explicit inline.

Why One Definition Rule, not One Declaration Rule?

I have read materials below:
https://www.wikiwand.com/en/One_Definition_Rule
http://en.cppreference.com/w/cpp/language/definition
What is the difference between a definition and a declaration?
But still, can't figure out why it is One Definition Rule rather than One Declaration Rule?
I maintain that declaration is a subset of definition, so One Definition Rule is enough.
One declaration rule would be too strict, preventing programs that use the same header more than once from compiling. It would also make it impossible to define data structures with back references.
A simple way to see the first point (using headers) is to consider a program composed of two translation units, A.cpp and B.cpp, which both include <string> header.
Translation units A.cpp and B.cpp are translated independently. By including <string>, both translation units acquire a declaration of std::string.
As for the second point (data structures with back references) consider an example of defining a tree in which each node has a back reference to its parent tree:
// Does not compile
struct tree {
struct node *root;
};
struct node {
struct node *left;
struct node *right;
struct tree *owner;
};
This example would not compile, because node from struct node *tree is undeclared. Switching the order of struct node and struct tree declarations wouldn't help, because then tree from struct tree *owner would be undeclared. The only solution in C and C++ is to introduce a second declaration for either of the two structs.
Because the same declaration, in a .h file, may be included in multiple compilation units, and because multiple definitions is definitely a programming error, whereas multiple declarations isn't.
Definition is a subset of declaration, not the other way around. Every definition is a declaration, and there are declarations that are not definitions.
int i = 3; // definition and declaration
extern int i; // ok: (re)declaration
int i = 4; // error: redefinition
extern int j; // declaration
extern int j; // ok: (re)declaration
int j = 5; // ok: (re)declaration and definition
int j = 6; // error: redefinition
Because when you have declared a function in a header file
// header toto.h
int f(void);
and you want to define it in the compilation unit where it belongs, you'd do
#include "toto.h"
int f(void) {
return 0;
}
The definition is also a declaration, so this compilation unit sees two declarations, one in the header and one in the .c or .cpp file.
In short, the multiple declaration rule allows to check for consistency between different source files.
The reason is really that the C++ translation model can easily deal with conflicting multiple declarations; it just requires the compiler part of the toolset to detect errors like this in the source code:
int X();
void X(); // error
A compiler can easily do that.
And when there are no such errors in any translation units, then there's no problem; every X() call in every translation unit is identical; what remains to do is for the linker to link every call to the one correct destination. The declarations have done their job and no longer play a role.
Now with multiple definitions, it's not that easy. Definitions are something which concerns multiple translation units and which goes beyond the scope of the compilation phase.
We've already seen that in the example above. The X() calls are in place, but now we need the guarantee that they all end up at the same destination, the same definition of X().
That there can be only one such definition should be clear, but how to enforce it? Put in simple terms, when it's time to link the object code together, the source code has already been dealt with.
The answer is that C++ basically chooses to put the burden on the programmer. Forcing compiler/linker implementors to check all multiple definitions for equality and detect differences would be beyond the capabilities of C++ toolsets in most real-life situations or completely break the way those tools work, so the pragmatic solution is to just forbid it and/or force the programmer to make sure that they are all identical or else get undefined behaviour.

Is there a difference between defining member functions inside vs outside the class definition?

Consider the following four member function declarations and definitions:
// ==== file: x.h
#ifndef X_H
#define X_H
class X {
public:
int a(int i) { return 2 * i; }
inline int b(int i) { return 2 * i; }
int c(int i);
int d(int i);
};
inline int X::c(int i) { return 2 * i; }
int X::d(int i) { return 2 * i; }
#endif
For completeness, here's the .cpp file that instantiates an X and calls the methods...
// ==== file: x.cpp
#include "x.h"
#include <stdio.h>
int main() {
X x;
printf("a(3) = %d\n", x.a(3));
printf("b(3) = %d\n", x.b(3));
printf("c(3) = %d\n", x.c(3));
printf("d(3) = %d\n", x.d(3));
return 0;
}
My question: are there any salient differences among the four methods? I understand from a comment in this post that the compiler may automatically inline methods that are defined in the class definition.
update
Many answers assume that I'm asking about the difference between inlining and not. I'm not. As I mentioned in the original post, I understand that defining a method in the header file gives the compiler license to inline the method.
I also (now) understand that method d is is risky as written: since it is not inlined, it will be multiply defined if there are multiple translation units.
My question remains: are there any salient differences among the four methods? (As noted, I know that method d is different). But -- just as important -- are there stylistic or idiomatic considerations that would make a developer choose one over the others?
Since this answer keeps getting upvotes, I feel obligated to improve it. But much of what I'm adding has already been stated in other answers and comments, and those authors deserve the credit.
On the subject of whether there's a difference between placing a function body inside the class definition or just below it (but still in the header file), there are 3 different cases to think about:
1) The function is not a template and is not declared to be inline. In this case it must be defined in the class definition or a separate cpp or you will get a linker error as soon as you try to include the h in more than one compilation unit.
2) The function is a template, but is not declared inline. In this case, putting the body within the class definition provides a hint to the compiler that the function can be inlined (but the final decision is still at its own discretion).
3) The function is declared to be inline. In this case there is no semantic difference, but it may sometimes be necessary to place the function body at the bottom in order to accommodate dependency cycles.
Original answer, which provides good info but does not address the actual question:
You've already noted the inline difference. In addition, defining member functions in the header means your implementation is visible to everyone. More importantly, it means everyone who includes your header also needs to include everything needed to make your implementations work.
If you are going to inline it regardless, then you'd move it out of the class if you want to be able to see all your members in one screen, or you have a cyclic dependency as mentioned below. If you don't want to inline it, then you have to move it out of the class and into an implementation file.
In the cases of classes that cyclically refer to each other, it may be impossible to define the functions in the classes so as to inline them. In that case, to achieve the same effect, you need to move the functions out of the classes.
Doesn't compile:
struct B;
struct A {
int i;
void foo(const B &b) {
i = b.i;
}
};
struct B {
int i;
void foo(const A &a) {
i = a.i;
}
};
Does compile, and achieves the same effect:
struct B;
struct A {
int i;
inline void foo(const B &b);
};
struct B {
int i;
inline void foo(const A &a);
};
inline void A::foo(const B &b) {
i = b.i;
}
inline void B::foo(const A &a) {
i = a.i;
}
Oops, just realised you had the definitions in the header file. That creates problems if the include file is included in more than one place.
If the functions are defined in a CPP file then there is no difference.
The only time it makes sense to implement a function inline is when the function is very clearly trivial and/or it has performance implications.
For all other times, it's best to put them in a .cc file and keep its implementation not exposed to the user of the class.
As pointed out by user3521733, it is impossible to implement some functions in the header file when there are cyclic dependencies. Here you are forced to put the implementations in a .cc file.
Update
As far as the compiler, and the runtime, is concerned, there is no difference that I can think of between defining the function inside the body of the class or outside if you use inline when defining it outside the body of the class.
X::a, X::b and X::c are all inlined. X::d is not. That's the only real differnce between these functions, aside from the fact that they are all different functions. The fact that X::c is defined in the header is irrelevant. What is relevant there is that the definition is marked inline.
In order to understand what the differences are, it's important to understand what inline is and is not. inline is not a performance tweak. It's not about making your code faster, and it's not about blowing the code out inline.
What it is about is the ODR. A function marked inline will have the exact same definition in each translation unit where it is used.
This comes in to play when you try to #include your file above in two or more CPP files and call X::d in those translation units. The linker will complain that X::d is defined more than once -- you've violated the ODR. The fix to this is to either mark the function inline or move the definition to it's own translation unit. (eg, to a CPP file)

C++ Basic Class Layout

Learning C++ and see the class laid out like this:
class CRectangle {
int x, y;
public:
void set_values (int,int);
int area () {return (x*y);}
};
void CRectangle::set_values (int a, int b) {
x = a;
y = b;
}
I know Java and methods(functions) in Java are written within the class. The class looks like a Java interface. I know I can write the class like this:
class CRectangle {
int x, y;
public:
void set_values (int a, int b) {
x = a;
y = b;
};
int area () {return (x*y);}
};
But is there a difference or standard?
There's a difference. When you write the definition of the function within the class definition (case 2), then the function is considered to have been declared inline. This is standard C++.
Usage, is to declare the member functions (Java methods) within the class definition, in a header file (.h), and to define these member functions in a C++ file (.cpp, .cc, or .C, …) This reduces compilation time, when you change the body of a function, only the C++ file has to be compiled, whereas if you change something in the header file, all C++ files that include this header are to be compiled.
It's much cleaner if you only define prototypes in the class definition (which belongs into a header file) and implement the methods in a cpp file.
When you have very small classes doing everything in the class definition might sound easier since everything is at the same place, but as soon as your class grows any developer using it will hate you since he'll have your code between the method prototypes he might look at to find out something (not everyone uses an IDE which shows all available methods!).
However, there is one exception: Template class methods needs to be implemented in the header as they need to be compiled for every specialization of the template.
The usual way is to put the implementation of functions within a separate cpp file, which is not included by other files, just compiled. This way it is easier to manage dependencies.
If the implementation of a function is given within the class definition (as in your 2nd example), this is a hint for the compiler to inline that function (which it may or may not do in the end, depending on e.g. the internals of the function). As a rule of thumb, function bodies longer than a few lines of code are better put into the cpp file, as these are probably not going inlined, however these may include extra dependencies and clutter the class definition.
The exception is template functions, where the bodies need to be in the header too, for the compiler must see them in order to instantiate the template.
I believe that if the method body is inside the class definition, then it is inlined everywhere is it called.
In C++, member functions which are defined in class are implicitly inline, member functions defined outside the class are not.
This affects the linkage of your two examples - the linker will complain about multiple definitions if the first example is #included in multiple source files, whereas the second example will not.
In terms of what's standard/normal:
The first form is used for complex classes, where the implementation of the functions requires extra headers to be pulled in.
The second form is used for simple classes which don't have extra dependencies.
Either form is used for template classes based on developer preference.
There is a slight difference in that functions defined inside the class are automatically inline. The latter definition can be put into a separate file. Otherwise there is no difference nor preference.
Note that we usually don't write semicolons after function definitions (though they are allowed inside a class definition).
void set_values (int a, int b) {
x = a;
y = b;
} // no semicolon here