在C++中使用内联函数的优点/缺点是什么?我看到它只会提高编译器输出的代码的性能,但是使用今天的优化编译器,快速CPU,大容量存储器等(不像1980年那样<内存稀缺,一切都必须适合100KB内存)什么他们今天真的有优势吗?
我是一名C/C++开发人员,这里有几个问题总让我感到困惑.
谢谢
从这里:
指令和数据具有不同的访问模式,并访问不同的内存区域.因此,对于指令和数据具有相同的高速缓存可能并不总是有效.
因此,拥有两个缓存是相当普遍的:仅存储指令的指令缓存和仅存储数据的数据缓存.
知道指令和数据之间的区别是直观的,但现在我不确定这种情况下的区别吗?什么构成数据并被放入数据缓存中,什么构成指令并被放入指令缓存?
我知道ARM组装.请问什么需要STR,LDR,LDMF或者STMFD使用数据缓存?但是从技术上来讲STR,LDR,LDMF和STMFD都说明,所以我这就是为什么我很困惑."数据"必须始终存在"指令"吗?是否在该.data部分中考虑了数据?
例如,LDR R1, =myVar那么LDR会进入指令缓存并且myVar的内容会进入数据缓存吗?或者它不是那样的工作?
说明和数据有不同的访问模式有人可以详细说明吗?
我在一篇有用的帖子上发表的评论突显了我难以理解:
"我的想法是,如果一条指令已经从内存中加载,它可能会很快再次使用",但知道下一条指令的唯一方法就是读取它.这意味着内存读取(你不能说它已经在缓存中了,因为新指令是红色的).所以我仍然没有看到这一点?说刚刚发生了LDR指令,所以现在LDR在数据缓存中.可能会发生另一条LDR指令,也许它不会发生,我们无法确定所以我们必须实际读取下一条指令 - 从而破坏了缓存的目的.
我注意到Google的C++样式指南警告不要使用循环或switch语句来内联函数:
另一个有用的经验法则:使用循环或switch语句内联函数通常不具成本效益(除非在通常情况下,从不执行循环或switch语句).
对StackOverflow的其他评论重申了这种观点.
为什么带有循环或switch语句(或gotos)的函数不适合或与内联兼容.这适用于包含任何类型跳转的函数吗?它适用于带if语句的函数吗?另外(这可能有些不相关),为什么内联函数不推荐使用值?
我对这个问题特别感兴趣,因为我正在处理一段对性能敏感的代码.我注意到在内联包含一系列if语句的函数后,性能下降得非常显着.我正在使用GNU Make 3.81,如果那是相关的.
我最近写了几堂课; 我想知道这是不好的做法,对性能有害,打破封装,还是在标题中实际定义一些较小的成员函数是否还有其他任何不妥之处(我确实试过谷歌!).这是一个我有一个标题的例子我写了很多这个:
class Scheduler {
public:
typedef std::list<BSubsystem*> SubsystemList;
// Make sure the pointer to entityManager is zero on init
// so that we can check if one has been attached in Tick()
Scheduler() : entityManager(0) { }
// Attaches a manager to the scheduler - used by Tick()
void AttachEntityManager( EntityManager &em )
{ entityManager = &em; }
// Detaches the entityManager from a scheduler.
void DetachEntityManager()
{ entityManager = 0; }
// Adds a subsystem to …Run Code Online (Sandbox Code Playgroud) 如果我内联一个函数.函数调用体将被复制,而不是向它发出一个call().为什么会导致糟糕的表现呢?
编辑:然后由于大功能而缓存未命中呢?为什么经验法则"仅存在最多3行的内联函数"?
假设编译器实际上内联foo是否存在这两个语句之间的性能差异?
inline int foo (int val) {
return val;
}
int main () {
std::cout << foo(123) << std::endl;
std::cout << 123 << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
让我们忽略移动语义和复制省略可能带来的任何影响.