web-dev-qa-db-ja.com

C ++で関数をインラインで宣言する必要がある場合

私はC++の良い習慣を使って、以前に書いたコードを書き直そうとしています。このような目標を達成するために、参考として使用しています Effective C++ (1)と googleコーディング規約 (2)。 (2)によると、関数が10行以下の場合はインラインで宣言する必要があります。(1)によれば、コンパイラはインラインディレクティブを無視できます。たとえば、ループや再帰がある場合(いくつかの例が提供されるだけなので、コンパイラによって無視されるすべてのケースを知っているわけではありません)。

次に、2つの関数があるとします。最初の関数は10行です。他の関数への呼び出しはなく、一般に外部参照はありません。 2番目はまだ10行であると想定していますが、ある時点で最初の1行が呼び出されます

何かのようなもの

Type1 f(Type2 arg) {
   //10 lines of self contained code
}

Type3 g(Type4 arg) {
   //0 <= n <= 8 lines of code
   //g(x);
   //9 - n lines of code
}

Googleからの提案により、fをインラインで宣言します(完全に正当化されます)が、gについて戸惑うことになるでしょう。 gをインラインとして宣言するとコンパイラは無視しますか?できない場合でも、インラインディレクティブの利点を利用できますか?

3
user8469759

C++では、inline指定子は、コンパイラーが関数呼び出しをインライン化するかどうかには影響しません。インライン化を可能にする効果がありますが、それが主な目的ではありません。インライン化したいプライベートヘルパー関数がある場合は、代わりに、その関数に内部リンケージがあることを確認してください。匿名の名前空間に配置する(C++ 11)。内部リンケージのある宣言には、現在のコンパイル単位内からのみアクセスできます。

inline関数は複数の定義を持つことができます。これは、ヘッダーファイル内で関数を定義するときに重要です。通常、関数はヘッダーで宣言し、それを.cppファイルに実装します。他のコンパイル単位はヘッダーに宣言を含み、後で定義にリンクされます。ただし、関数がヘッダーで定義されている場合、同じ関数が複数のコンパイル単位に存在します。それらがリンクされると、リンカーは関数のこれらの複数の定義を参照します。正しい定義はどれですか?リンカはエラーを発生させます。

inline指定子を使用して、これらの複数の定義に問題がなく、すべて同じ関数を参照していることをリンカーに通知します。さらに、inline関数の定義は同じコンパイル単位に存在する必要があります。

一部の関数は暗黙的にインライン化されています。特に、クラス宣言内のメソッドと関数は次のとおりです。

class Foo {
public:
  void method() { /* implicitly inline */ }
  static void static_method() { /* implicitly inline */ }
  friend void friend_function() { /* implicitly inline */ }
};

void free_function() { /* not implicitly inline */ }

関数は短いので、インラインとして宣言しないでください。ヘッダーで定義したため、インラインとして宣言します。

さらに読む: inline cppreference.comの指定子

引用するGoogleスタイルガイドでは、inlineキーワードを使用するタイミングについては説明していませんが、関数をインラインで(つまり、ヘッダーファイルに)実装する必要があるかどうかを説明しています。クラスのゲッターのような単純な関数の場合、これは通常完全に問題ありません。大規模で複雑な関数の場合、通常は個別に実装することをお勧めします(これはテンプレートでは不可能です)。

15
amon