の移動操作(移動コンストラクターのような)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::move
shared_ptr
データメンバへのパラメータは:refカウントがないではない変更します!ポインタ/状態を盗むだけです。高価なアトミック参照カウント操作は必要ありません。
- メソッドを終了すると、
shared_ptr
パラメーターは破棄されます。しかし、ステップ2で移動したので、shared_ptr
パラメーターがもう何も指していないため、破壊するものはありません。この場合も、アトミックデクリメントは発生しません。
結論:この場合、参照カウントのアトミック増分は1つしか得られません。つまり、アトミック操作は1つだけです。
ご覧のように、これは、コピーの場合の2つのアトミックインクリメントと1つのアトミックデクリメント(合計3つのアトミック操作)よりもはるかに優れています。