这里是几份C++代码:
a.h
#include <iostream>
#ifndef STR
#define STR "default"
#endif
struct A {
static void print() { std::cout << STR; }
};
imp1.cc
#define STR "imp1"
#include "a.h"
void imp1() { A::print(); }
imp2.cc
#define STR "imp2"
#include "a.h"
void imp2() { A::print(); }
main.cc
void imp1();
void imp2();
int main() { imp1(); imp2(); }
我们知道,在类定义中定义的函数默认是inline函数,inline函数将建议编译器在行内展开代码。那么main打印的是imp1, imp2还是str?
我找不到相关的资料。相同的代码,编译命令为g++ main.cc imp1.cc imp2.cc
时,在GCC 6.1.1上面是打印imp1imp2
,在MinGW GCC 4.8.1上面是打印imp1imp1
。在编译命令为g++ imp2.cc imp1.cc main.cc
,在GCC 6.1.1上面没有变化,在MinGW GCC 4.8.1上面是打印imp2imp2
。
请问C++ standard有相关规定(也就是说是MinGW的bug),还是未定义行为呢?
I tried it. If gcc is optimized with -O2 or -O1, the result will be imp1imp2. If it is optimized with -O0, the result will be imp1imp1 or imp2imp2
The reason should be that inline will be ignored by gcc without -O optimization to facilitate debugging.
Inline in the standard should be a suggestion, not a mandatory requirement. Without inline, the order of the .o files becomes the deciding factor.
It should be that GCC does not perform inline (even if you write inline, the compiler does not guarantee that it will perform inline). In this case, at the link stage, for the reference of A::print, which .o file is used for A:: Print is possible (all are weak symbols), but only one will be used.
The poster needs to understand the compilation process,
1. Preprocessing
2. Compilation
3. Assembly
4. Linking
define in the preprocessing phase
inline in the compilation phase
This should make it clear
Environment:
The result of clang -O0 -O1 is
imp1imp1
The result of clang -O2 -O3 is
imp1imp2
I modified the code to force the use of inlining:
It is
under any optimization switchimp1imp2
And when the code forcibly prohibits inlining:
The result is related to the file order:
The explanation is as follows:If
imp1.cpp
is ranked first, it isimp1imp1
under any optimization switch;If
imp2.cpp
is ranked first, it is ;imp2imp2
When inlining is forced, the macros of the inline function will be replaced independently in the two files;
Except for member functions, if an ordinary inline function (non-member, non-static-member) is defined in a header file, it will cause a compilation error due to redefinition; while it will not occur at all if it is defined in cpp Affected by macros in other files.When inlining is disabled, the macros of the inline function will be compiled in the first The unit is replaced (because if it is replaced in multiple compilation units, it is equivalent to inlining).
When not forced (no
), the compiler will turn off inlining under -O0 -O1, and only turn it on under -O2 -O3.
__attribute__