pimpl中的方法是否内联?

时间:2011-06-06 11:17:52

标签: c++ inline pimpl-idiom

考虑下一个简单的例子:

标题:

// 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

实施:

// 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();
}

主要:

// main.cpp
#include "header.hpp"
int main()
{
  A a;
  return a.foo();
}

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

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

修改

我想我没解释得很好。我的意思是这个。如果我使用最高优化级别,那么// do something and return the resultA::foo()还是A::Imp::foo()? 如果没有优化,我发现这没有完成(仍然调用the pimpl->foo())。

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

2 个答案:

答案 0 :(得分:10)

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

答案 1 :(得分:8)

Herb Sutter曾做过一篇关于内联的精彩文章。

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

在C ++中:

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

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

因此关键点是知道实现位。

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

所以在这里:是的,可以在pimpl->foo()内内联呼叫A::foo。它将取决于编译器编译选项。

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