pimpl中的方法是否内联?

BЈо*_*вић 3 c++ pimpl-idiom inline

考虑下一个简单的例子:

标题:

// a.hpp
#ifndef A_HPP
#define A_HPP
#include <memory>

class A
{
 public:
  A();

  int foo();

 private:
  struct Imp;
  std::auto_ptr< Imp > pimpl;
};

#endif // A_HPP
Run Code Online (Sandbox Code Playgroud)

实施:

// a.cpp
#include "a.hpp"

struct A::Imp
{
 int foo()
 {
  // do something and return the result
 }
};

A::A() : pimpl( new Imp )
{}
int A::foo()
{
  return pimpl->foo();
}
Run Code Online (Sandbox Code Playgroud)

主要的 :

// main.cpp
#include "header.hpp"
int main()
{
  A a;
  return a.foo();
}
Run Code Online (Sandbox Code Playgroud)

问题是:
方法是否A::Imp::foo会被内联到A::foo
它取决于实现该方法中的内容吗?

PS我正在使用gcc(4.3.0如果重要的话).

编辑

我想我没解释得很好.我的意思是这个.如果我使用最大优化级别,是否// do something and return the result会被放置在A::foo()A::Imp::foo()
没有优化,我发现这没有完成(the pimpl->foo()仍然被称为).

我知道A :: foo()永远不会在main()中内联,但这不是我要问的.

小智 10

所有内联都依赖于实现.如果这对您很重要,请查看发出的汇编程序代码.


Mat*_* M. 8

Herb Sutter曾做过一篇关于内联的伟大文章.

要问的第一个问题是:何时可以进行内联?

在C++中:

  • 它可能发生在编译阶段
  • 它可能发生在链接阶段(LTO:链接时间优化)

两次,机制都类似:如果编译器/链接器知道该方法的实现,它可能决定复制/粘贴实现而不是发出调用.这个决定是基于复杂的启发式方法,我只知道它们存在,而不是它们的含义.

因此关键点是了解实现位.

  • 对于编译器:它表示在同一个翻译单元中定义
  • 对于链接器:它意味着在一个链接的转换单元中定义或在静态库中它将链接到... afaik如果方法驻留在DLL中它将不会被优化

所以这里:是的,pimpl->foo()可以在内部调用内容A::foo.它取决于编译器编译选项.

对于gcc/clang,如果A::Impl::foo足够小,可以从O1开始优化(除非你通过-fno-inline).