30秒到达战场
我想用一个令人信服的例子来解释这篇文章中所有的伟大答案,以消除任何剩余的误解。给定两个源文件,例如:inline111.cpp:#include <iostream>void bar();inline int fun() {
return 111;}int main() {
std::cout << "inline111: fun() = " << fun() << ", &fun = " << (void*) &fun;
bar();}inline222.cpp:#include <iostream>inline int fun() {
return 222;}void bar() {
std::cout << "inline222: fun() = " << fun() << ", &fun = " << (void*) &fun;}案例A:编译:g++ -std=c++11 inline111.cpp inline222.cpp输出量:inline111: fun() = 111, &fun = 0x4029a0inline222: fun() = 111, &fun = 0x4029a0讨论:即使您应该对内联函数有相同的定义,如果情况并非如此,C+编译器也不会标记它(实际上,由于单独汇编它没有办法检查)。确保这一点是你自己的责任!链接器不抱怨一种定义规则,如fun()被宣布为inline..但是,因为inline111.cpp是第一个翻译单元(它实际上调用fun())由编译器处理,编译器实例化fun()在它第一打电话inline111.cpp..如果编译器决定不扩大fun()应您程序中其他任何地方的要求(G.从…inline222.cpp)的电话fun()将始终链接到其生成的实例。inline111.cpp(电话:fun()内inline222.cpp也可以在该翻译单元中生成一个实例,但它将保持不链接)。事实上,这一点从相同的&fun = 0x4029a0打印出来。最后,尽管inline对编译器的建议实际扩展一条龙fun(),它视而不见你的建议很清楚,因为fun() = 111在这两条线上。案例B:编译 (通知反向命令):g++ -std=c++11 inline222.cpp inline111.cpp输出量:inline111: fun() = 222, &fun = 0x402980inline222: fun() = 222, &fun = 0x402980讨论:这个案例证明了案件A.注意一个重要的问题,如果您注释掉实际调用fun()在……里面inline222.cpp (G.注释掉cout-声明inline222.cpp完全)那么,尽管你的翻译单位的汇编顺序,fun()中的第一次调用时将被实例化。inline111.cpp的打印结果案例B如inline111: fun() = 111, &fun = 0x402980.案例C:编译 (公告-O2):g++ -std=c++11 -O2 inline222.cpp inline111.cpp或g++ -std=c++11 -O2 inline111.cpp inline222.cpp输出量:inline111: fun() = 111, &fun = 0x402900inline222: fun() = 222, &fun = 0x402900讨论:原样在此描述, -O2优化鼓励编译器实际扩展可以内联的函数(也请注意,-fno-inline是违约没有优化选项)。从这里的输出可以看出,fun()实际上内联扩展(根据它的定义特别翻译股),产生两个异类 fun()打印出来。尽管如此,还是有只有一个全局链接实例fun()(按照标准的要求),从完全相同 &fun打印出来。