Defined multiple times for the inline function, how possible?
Asked Answered
A

3

6

The following quote from c++ primer book confuse me a lot

Unlike other function, inline and constexpr functions may be defined multiple times in the program. After all, the compiler needs the definition, not just the declaration, in order to expand the code. However, all of the definitions of a given inline or constexpr must match exactly. As a result, inline and constexpr functions normally are defined in headers. -- C++ primer 5th Ed, 240 pp

"may be defined multiple times in the program" This quote confuse me a lot. As far as I understand, declaration can be made multiple time, but definition is only needed once.

can someone give me an example why there is a multiple definition.

Audiology answered 29/11, 2018 at 16:27 Comment(2)
That's what make inline (and constexpr, which implies inline) functions special: they can have several definitions.Hinduism
Related question: #35233968Broadside
H
3

In a header file (lets call it foo.h) you can have

inline int foo() { /* do stuff */ }

Now if you include foo.h in a couple cpp files then foo will be defined in each of them, which would be a multiple definition error. Since foo is marked as inline though, it is okay because all of the definitions are the same.

As far as I understand, declaration can be made multiple time, but definition is only needed once

The compiler works on translation units (basically a cpp file) and in it, it can do all sorts of optimizations but function inlining and constexpr require that the compiler know the definition of the function. That means each translation unit needs the definition of the function in it. We use inline to make that okay, otherwise it would be a multiple definition error.

Heimdall answered 29/11, 2018 at 16:30 Comment(0)
B
4

As an example. This version isn't valid.

// main.cpp
inline int square(int num) {
    return num * num;
}

inline int square(int num) {
    return num * num;
}

int main()
{
    return square(2);
}

https://godbolt.org/z/nlSbxg

But when you have it in multiple .cpp files (aka. translation units) it is ok because it is now linker job to do right thing.

// b.cpp
inline int square(int num) {
    return num * num;
}

// main.cpp
inline int square(int num) {
    return num * num;
}

int main()
{
    return square(2);
}

Build: gcc main.cpp b.cpp Same way works #include it will place code in those .cpp files that's all.

Of course if body of function is inlined, then nothing to link so no problem :)

If compiler decides to do an out-of-line version you end up with more than one object file (.o) having definition for the same "inline" function. Such definition will be marked.

Thanks to that mark linker won't yield that it has found multiple definitions and just pick first one that it finds.

So if all definitions are truly the same, then fine! We will get into troubles if we have different body of such function. Example in file b.cpp

// b.cpp
inline int square(int num) {
    return 1;
}

It is undefined behavior to have multiple different definitions of the same inline function. It will compile of course but what we get? It depends on linker choice :D

Broadside answered 29/11, 2018 at 16:46 Comment(0)
H
3

In a header file (lets call it foo.h) you can have

inline int foo() { /* do stuff */ }

Now if you include foo.h in a couple cpp files then foo will be defined in each of them, which would be a multiple definition error. Since foo is marked as inline though, it is okay because all of the definitions are the same.

As far as I understand, declaration can be made multiple time, but definition is only needed once

The compiler works on translation units (basically a cpp file) and in it, it can do all sorts of optimizations but function inlining and constexpr require that the compiler know the definition of the function. That means each translation unit needs the definition of the function in it. We use inline to make that okay, otherwise it would be a multiple definition error.

Heimdall answered 29/11, 2018 at 16:30 Comment(0)
P
2

I think the problem is that there are multiple things we can mean by "define." When you write an inline function in a header file, it's "defined" just once in the sense that there is only a single function with that name in your source code.

But that's not how the compiler and linker see the world. If you have an inline function foo in a header file that's called from a.cpp and b.cpp, then the complete compiled version of that function will be included in both a.obj and b.obj. The linker resolves the issue by picking just one of those compiled versions to include in your final binary.

Note that I'm glossing over significant details here, but this is the general idea (and what I think your textbook is eluding to).

Portal answered 29/11, 2018 at 16:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.