の移動操作(移動コンストラクターのような)std::shared_ptrは、基本的に「ソースから宛先へのポインタを盗む」ため、安価です。正確には、状態制御ブロック全体が、参照カウント情報を含め、ソースから宛先に「盗まれます」。 。
代わりに 、コピーの操作をstd::shared_ptr呼び出し、原子(すなわちだけでなく、参照カウントの増加++RefCount整数上のRefCountデータメンバが、例えば、呼び出し元InterlockedIncrementよりあるWindowsの場合)、高価ポインター/状態を単に盗むよりもます。
したがって、このケースの参照カウントダイナミクスを詳細に分析します。
// shared_ptr<CompilerInvocation> sp;
compilerInstance.setInvocation(sp);
sp値で渡し、メソッド内でコピーを取ると、次のようになりCompilerInstance::setInvocationます。
- メソッドに入るとき、
shared_ptrパラメーターはコピー構築されます:ref count atomic increment。
- メソッドの本体の中で、
shared_ptrパラメーターをデータメンバーにコピーします。ref count atomic increment。
- メソッドを終了すると、
shared_ptrパラメーターは破棄されます:ref count atomic decrement。
2つのアトミックインクリメントと1つのアトミックデクリメントがあり、合計3つの アトミック操作があります。
代わりに、 shared_ptrパラメーターを値でstd::moveメソッド内で(Clangのコードで正しく行われるように)と、次のようになります。
- メソッドを入力すると、
shared_ptrパラメーターはコピー構築されます:ref count atomic increment。
- メソッドの本体の中で、
std::moveshared_ptrデータメンバへのパラメータは:refカウントがないではない変更します!ポインタ/状態を盗むだけです。高価なアトミック参照カウント操作は必要ありません。
- メソッドを終了すると、
shared_ptrパラメーターは破棄されます。しかし、ステップ2で移動したので、shared_ptrパラメーターがもう何も指していないため、破壊するものはありません。この場合も、アトミックデクリメントは発生しません。
結論:この場合、参照カウントのアトミック増分は1つしか得られません。つまり、アトミック操作は1つだけです。
ご覧のように、これは、コピーの場合の2つのアトミックインクリメントと1つのアトミックデクリメント(合計3つのアトミック操作)よりもはるかに優れています。