4

次の簡単な例を考えてみましょう:

ヘッダー:

// 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 resultに配置されますA::foo()A::Imp::foo()?
最適化がなければ、これは行われていないことがわかります (the pimpl->foo()はまだ呼び出されています)。

A::foo() が main() でインライン化されることはないことは理解していますが、それは私が求めていることではありません。

4

2 に答える 2

10

すべてのインライン化は実装に依存します。これが問題になる場合は、出力されたアセンブラー コードを見てください。

于 2011-06-06T11:19:36.247 に答える
10

Herb Sutter はかつて、インライン化に関する素晴らしい記事を作成しました。

最初の質問は次のとおりです。インライン化はいつ行われますか?

C++ の場合:

  • コンパイル段階で発生する可能性があります
  • リンク段階で発生する可能性があります (LTO: Link Time Optimization)

どちらの場合もメカニズムは似ています。コンパイラ/リンカーがメソッドの実装を認識している場合、呼び出しを発行する代わりに実装をコピー/貼り付けすることを決定できます。この決定は複雑なヒューリスティックに基づいており、私はそれらが存在することだけを知っており、それらが何であるかは知りません.

したがって、重要な点は、実装ビットについて知っていることです。

  • コンパイラの場合: 同じ翻訳単位で定義されていることを意味します
  • リンカーの場合:リンクされている翻訳単位の1つで定義されているか、リンク先の静的ライブラリで定義されていることを意味します...メソッドがDLLに存在する場合、最適化されません。

だからここ:はい、呼び出しpimpl->foo()は内でインライン化される可能性がありますA::fooこれは、コンパイラとコンパイル オプションの両方に依存します。

gcc/clang の場合、A::Impl::fooが十分に小さければ、O1 以降で最適化できます ( を渡さない限り-fno-inline)。

于 2011-06-06T11:59:24.997 に答える