inline
キーワードの使用には2つの意味があります(§7.1.3/4):
通常、メインストリームコンパイラは必要に応じて呼び出しポイントで関数本体を置換するため、関数inline
を単に#1
は実際には必要ありません。
さらにw.r.t #2
、関数をstatic inline
関数、
関数のstatic
キーワードは、inline
関数に内部リンケージを強制します(インライン関数には外部リンケージがあります)このような関数の各インスタンスは、個別のインスタンスとして扱われますfunction(各関数のアドレスが異なる)、これらの関数の各インスタンスには、静的ローカル変数と文字列リテラルの独自のコピーがあります(インライン関数にはこれらのコピーが1つしかありません )
したがって、このような関数は他のstatic
関数と同様に機能し、キーワードinline
はもはや重要ではなくなり、冗長になります。
そのため、関数static
とinline
の両方を実際にマークすることは、まったく役に立ちません。 static
(最も優先されない)またはinline
(最も優先される)、
それで、関数でstatic
とinline
を一緒に使用しています実際には役に立たない?
あなたの分析は正しいが、必ずしも役に立たないという意味ではない。ほとんどのコンパイラが関数を自動的にインライン化する場合でも(理由#1)、意図を記述するためだけにinline
を宣言するのが最善です。
inline
、static
関数との相互作用を無視することは控えめに使用する必要があります。名前空間スコープのstatic
修飾子は、以前は名前のない名前空間を優先するために廃止されました(C++ 03§D.2)。 C++ 11の非推奨から削除されたことを思い出せない不明瞭な理由により、ほとんど必要ないはずです。
したがって、関数を静的とインラインの両方に実際にマークすることは、まったく役に立ちません。静的(最も優先されない)またはインライン(最も優先される)である必要があります。
好みの概念はありません。 static
は、同じシグネチャを持つ異なる関数が異なる.cpp
ファイル(翻訳単位)。 inline
をstatic
なしで使用すると、異なる翻訳単位で同じ関数を同じ定義で定義してもかまいません。
isが望ましいのは、static
の代わりに名前のない名前空間を使用することです:
namespace {
inline void better(); // give the function a unique name
}
static inline void worse(); // kludge the linker to allowing duplicates
静的およびインラインは直交(独立)です。静的とは、関数が翻訳単位の外に表示されるべきではないことを意味します。インラインは、プログラマがこの関数をインライン化することを望むコンパイラへのヒントです。これら2つは関連していません。
static inline
を使用することは、インライン化された関数が翻訳単位の外部で使用されない場合に意味があります。これを使用することにより、同じ名前の別の翻訳単位で別のインライン関数に名前を付けることで、ODRルールの偶発的な違反の状況を防ぐことができます。
例:
source1.cpp:
inline int Foo()
{
return 1;
}
int Bar1()
{
return Foo();
}
source2.cpp:
inline int Foo()
{
return 2;
}
int Bar2()
{
return Foo();
}
Fooでstaticを使用しない(またはほとんどのC++プログラマーが好む匿名名前空間を使用しない)場合、この例はODRに違反し、結果は未定義です。 Visual Studioでテストできます。Bar1/ Bar2の結果はコンパイラの設定に依存します-デバッグ構成では、Bar1とBar2の両方が同じ値を返します(インライン展開は使用されず、1つの実装はリンカによってランダムに選択されます)。意図した値を返します。
私はこれについて完全に正しいわけではないかもしれませんが、関数の宣言を知っている限り_static inline
は、コンパイラがマシンコードを生成する(または許可する)唯一の方法であり、関数はコンパイルされたコードで実際に定義されておらず、宣言された関数を命令のシーケンスに直接置き換えるだけです。 、ソースコードからのその関数定義に関連するプロシージャコールのマシンコードにトレースのない、単なる通常のプロシージャボディのように。
つまり、static inline
マクロの使用を実際に置き換えることができます。inline
だけでは十分ではありません。
「静的インライン」をGoogleで簡単に検索すると、コンパイラのドキュメントページが表示されます。これはあなたの質問に答えるのに十分であると思い、「いいえ、それは実際には役に立たない」と言います。 inline
の使用、特にstatic inline
http://www.greenend.org.uk/rjk/tech/inline.html
free関数(namespace
スコープ)について話す場合、あなたの仮定は正しいです。 static inline
関数は実際にはあまり価値がありません。そう static inline
は、単にstatic
関数であり、自動的にODRを満たし、inline
はODRの目的のために冗長です。
ただし、メンバーメソッド(class
スコープ)について話すとき、static inline
関数には値があります。class
メソッドをinline
として宣言したら、class
を含むすべての翻訳単位で完全なボディを表示する必要があります。
static
の場合、class
キーワードは異なる意味を持つことに注意してください。
Edit:ご存じかもしれませんが、static
内のclass
関数には内部リンケージがない、つまりクラスはできません変換(.cpp)単位に応じて、static
メソッドのコピーが異なります。
ただし、static
/globalスコープの無料のnamespace
関数には、翻訳単位ごとに異なるコピーがあります。
例えば.
// file.h
static void foo () {}
struct A {
static void foo () {}
};
// file1.cpp
#include"file.h"
void x1 ()
{
foo(); // different function exclusive to file1.cpp
A::foo(); // same function
}
// file2.cpp
#include"file.h"
void x2 ()
{
foo(); // different function exclusive to file2.cpp
A::foo(); // same function
}
Gccのmanページを読んだだけで、コンパイラフラグを使用した静的インラインの使用について具体的に説明しています。フラグの場合、関数をインライン化し、静的であり、呼び出されるすべてのインスタンスでインライン化されている場合、作成されたオブジェクトファイルで決して使用されない関数定義を取り除きます。その少しだけ生成されたコードのサイズ。