【问题标题】:What does compiler really do when a class inline function is called?当调用类内联函数时,编译器真正做了什么?
【发布时间】:2017-09-22 08:16:51
【问题描述】:

没有一个静态成员函数隐式具有this 指针。所以这些内联函数在类外调用时不会被编译器替换,对吗?这似乎是类内联函数的使用非常有限!

【问题讨论】:

  • C 没有类,所以这是一个完成的交易。不过,我无法理解这个问题,你能用代码示例澄清一下吗?
  • 为什么你认为隐含的this 参数与内联有关?
  • 编译器可以内联它想要的任何函数,只要它确保信息正确传递并且代码按要求运行。但是,给定编译器的作用取决于编译器。
  • 这个逻辑是错误的。第一句和第二句之间没有联系。前者并不暗示/导致后者。

标签: c++ class inline


【解决方案1】:

优化的编译器可以根据需要inline

例如,您可以编译并链接整个程序与g++ -flto -O2(链接时整个程序optimization option of GCC...)。

(警告:使用g++ -flto -O2 会显着减慢您的构建过程;基本上所有内容都被编译几乎“两次”,一次在“编译”时间,一次在“链接”时间,GIMPLE 表示得到重新优化)

您会对内联的函数调用感到惊讶(其中很多可能是内联的)。它与静态或未标记为inline的函数无关。

所以你不应该关心内联(它是一个实现和优化细节),但你希望编译器会做得很好。

(有时对于g++,您希望禁用大多数内联以方便使用gdb 进行调试;然后编译with g++ -fno-inline -Wall -Wextra -O0 -g

所以这些内联函数在类外调用时不会被编译器替换,对吗?

你错了,this 只是一个隐式 参数(另见that),当然编译器经常内联对成员函数的调用。在实践中,如果编译器没有进行这种优化,C++ 的效率就会很低(因为许多成员函数 - 例如 getters 和 setters- 都非常短而快)。

请记住,C++ 是在某些报告中编写的规范(它不是编译器)。内联是实施质量问题,可能会发生也可能不会发生。

如果你关心编译器真正做了什么(你不应该关心,但你需要在你的代码中避免undefined behavior),让它显示生成的汇编代码。用GCCg++ -O2 -fverbose-asm -S 编译以从foo.cc 翻译单元获得foo.s 汇编程序文件。

【讨论】:

  • 你可以使用-fno-fat-lto-objects来防止双重编译。
  • 但是,LTO 编译仍然很慢
  • 但不是你写的两次。
  • 类似于“两次”。改进
【解决方案2】:

当调用内联成员函数时,编译器会执行它对任何函数调用所做的事情:准备参数并调用函数。任何函数调用都需要内联。某些函数无法内联(e.g. functions using alloca or vararg functions,其定义不可用的函数),但成员函数不会阻止内联。

【讨论】:

  • 您的意思是“某些函数不会被内联”。一个非常聪明的编译器理论上可以使用allocava_arg 内联函数;在 practice GCC还没有 能够做到这一点,但是如果你真的想要的话,你可以通过大量的工作来做到这一点(例如,花几个月的时间来为此编写一个 GCC 插件)
  • @BasileStarynkevitch 理论上可以。但是,我认为值得一提的是现有的一些限制。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-25
  • 1970-01-01
  • 2011-11-27
  • 2017-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多