如果C++的inline函数中有宏,行为是怎样的?
天蓬老师
天蓬老师 2017-04-17 14:39:14
[C++讨论组]

这里是几份C++代码:

a.h

#include 
#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),还是未定义行为呢?

天蓬老师
天蓬老师

欢迎选择我的课程,让我们一起见证您的进步~~

全部回复(2)
大家讲道理

应该是GCC没有进行inline(即使你写了inline,编译器也不保证进行inline),这样的话,到了链接阶段,对于A::print的引用,用哪个.o文件中的A::print都有可能(都是弱符号),但一定只会使用一个。

黄舟

环境:

Apple LLVM version 8.0.0 (clang-800.0.38)
Target: x86_64-apple-darwin16.0.0
Thread model: posix

clang -O0 -O1 的结果是 imp1imp1
clang -O2 -O3 的结果是 imp1imp2

我将代码修改了一下,强制使用内联:

struct A {
    __attribute__((always_inline)) static void print() { std::cout << STR; }
};

在任何优化开关下都是 imp1imp2

而当代码强制禁止内联的时候:

struct A {
    __attribute__((noinline)) static void print() { std::cout << STR; }
};

结果与文件顺序相关:
如果 imp1.cpp 排在前面,在任何优化开关下都是 imp1imp1
如果 imp2.cpp 排在前面,在任何优化开关下都是 imp2imp2

解释如下:
强制内联时,内联函数的宏会在在两个文件中被独立的替换;
禁止内联时,内联函数的宏会在第一个编译单元被替换(因为如果在多个编译单元被替换就等于内联了)。
未强制的时候(无 __attribute__)在 -O0 -O1下,编译器会关闭内联,而 -O2 -O3 下才打开。

除了成员函数之外,如果是普通内联函数(non-member,non-static-member)定义在头文件里,会引起编译错误,因为重定义;而定义在 cpp 里则根本不会被其他文件的宏所影响。

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号