跨翻译单元实验inline函数:非inline函数为何优先?是否违反ODR?
关于inline函数跨翻译单元的链接行为与ODR问题
我在跨翻译单元测试inline函数时遇到了如下场景:
// A.cpp #include <iostream> void f() { std::cout << "Bye" << std::endl; }
// main.cpp #include <iostream> inline void f() { std::cout << "Hello" << std::endl; } int main() { f(); return 0; }
使用g++ main.cpp A.cpp编译链接后运行,控制台输出“Bye”。以下是对问题的解答:
一、为什么输出“Bye”而非“Hello”?
这是链接器对符号优先级的处理逻辑导致的:
- C++中,普通非inline函数属于强符号(外部链接属性,整个程序中理论上只能存在一个定义);而inline函数默认被标记为弱符号(允许多个翻译单元存在定义,但链接时会被同名强符号覆盖)。
- 你的代码里,A.cpp中的
f()是非inline的强符号,main.cpp中的inline f()是弱符号。链接器合并目标文件时会优先选择强符号的定义,所以最终程序调用的是A.cpp里的f(),输出“Bye”。
二、这种情况是否违反One-Definition Rule(ODR)?
严格来说,这种情况完全违反了ODR:
- ODR对inline函数的明确要求是:如果一个inline函数在多个翻译单元中定义,那么所有定义必须完全一致——不仅函数体内容要token-for-token匹配,每个定义都必须带有
inline声明,且依赖的所有实体也需一致。 - 你的代码中,A.cpp的
f()没有inline声明,且函数体与main.cpp的版本完全不同,这直接违反了ODR规则。但ODR违反属于C++标准中的未定义行为,编译器和链接器不一定会主动报错,而是可能按各自的逻辑处理(比如这里的强符号覆盖弱符号),但这种行为不可移植、不能依赖。
内容的提问来源于stack exchange,提问作者Broseph_Stally
相关产品推荐
相关产品推荐

