2016-08-15 14 views
0

shared_ptrのコピー代入演算子を使用すると、割り当ての左側のshared_ptrは、現在所有しているオブジェクトの参照カウントをデクリメントしてからインクリメントする必要があります代入の右側のオブジェクトの参照カウント(。両方のポインタがNULLであることを、もちろん、と仮定)shared_ptr代入:参照カウントの順序

ので、実装は以下の擬似コードのようなものになります。

shared_ptr& operator = (const shared_ptr& rhs) 
{ 
    decrement_reference_count(this->m_ptr); 
    this->m_ptr = rhs.m_ptr; 
    increment_reference_count(this->m_ptr); 
    return *this; 
} 

をしかし、ここで私たちはthisの参照カウントをデクリメントことに注意してくださいの前にとなります。rhsの参照カウントをインクリメントします。私たちはまた、それを逆にすることもできます。私の質問は、標準が実際にここで注文を指定しているかどうかです。それはthisの参照カウントとlhsの参照カウント間の依存関係のいくつかの種類がある場合で大きな違いを生むことができます:それは違いを作るのはなぜ

。たとえば、リンクされたリスト構造の一部であり、リンクされた各ノード内のnextポインタがshared_ptrであるとします。そのため、構造内の任意のノードの参照カウントを減らすとデストラクタがトリガされ、チェーン内の他のノードごとに連鎖反応を開始し、参照カウントを減らします(おそらくは破棄する)。

我々最初thisをデクリメント、あるいは我々が最初にlhsをインクリメントあれば、lhsの参照カウントがthisの参照カウントの影響を受けている状況を想定し、それは大きな違いになります。最初にlhsをインクリメントしてからをデクリメントしてthisにすると、lhsがデクリメントされても最終的には破棄されないことがわかりますthis

実際には、この規格ではここで注文が指定されていますか?私の知る限り見ることができるように、標準が言う唯一のものは、コピー代入演算子は式と等価であるということである。

shared_ptr(lhs).swap(*this) 

しかし、(もしあれば)私は本当にこのことの意味まわりで私の頭をラップすることはできません等価性は、参照カウントを減分/インクリメントする順序に関して有する可能性がある。

標準ではここで注文を指定していますか?あるいは、この実装定義の振る舞いですか?

答えて

1

rhsthisの場合は、最初に参照カウンタをインクリメントする必要があります。それ以外の場合は、参照カウンタが1のときにpointeeを誤って破棄する可能性があります。this == &rhsであるかどうかを確認できますが、参照カウンタの増分が減分前に実行されている場合はこのチェックは不要です。

最初にコピーが作成され、最初に参照カウンタがインクリメントされるため、この問題は発生しません。

3

[20.7.2.2。3]

shared_ptr& operator=(const shared_ptr& r) noexcept; 

shared_ptr(r).swap(*this) 

と同等の効果を有する。これは、次いでデクリメントを意味し、一時的に破壊、*thisとのデータを交換する、rの参照カウントをインクリメントした、一時的に構築意味以前は*thisに属していた参照カウント。

関連する問題