4

事前にご協力いただきありがとうございます。私は Scott Meyers 著の「より効果的な C++」という本を読んでいますが、項目 29「参照カウント」の単純なプログラムの 1 つに本当に混乱しています。プログラムは次の場所にコピーされます。

String::String(const String& rhs): value(rhs.value) { ++value->refCount; }

次にコード:

String s1("More Effective C++");
String s2=s1;

なぜ s1 と s2 の両方が refCount 2 になるのか、私は本当に混乱しています。 refCount はまったく変更されません。私を修正してください!! 再度、感謝します。

よろしくお願いします。

4

5 に答える 5

3

valueこの場合はポインタであり、const-ness は指しているオブジェクトに伝播しないため、ここでrefCount 変更可能です。

参照カウントのポイントは、すべての参照がなくなるまで、つまり参照カウントがゼロになるまで、再作成せずに同じオブジェクト表現を共有することです。この時点で、表現は割り当て解除されます。

これは読み取り専用オブジェクトに最適です。そのため、参照インスタンスの 1 つがその共有表現を変更したい場合、通常は複製され、ref-counting は再び 1 から開始されます。

次に、参照カウントをスレッドセーフにする際の問題があります。Sutter はこれについて広く書いています。 gotw #43gotw #44、およびgotw #45を参照してください。

于 2012-07-15T23:34:24.403 に答える
3

s2.refCount2になることは理解していますが、s1.refCountまったく変わりません。

あなたの誤解があります。のような動物はありs2.refCountませんs1.refCount。むしろ、変数は と と呼ばれs2.value->refCountますs1.value->refCounts2.value==s1.valueであるため、本質的に同じrefCountメンバーを共有していることに注意してください。

于 2012-07-15T23:35:17.460 に答える
1

によって使用される参照カウントs1が 1 の場合、終了時に文字列を削除します。次の点を考慮してください。

String s2;
{
    String s1("More Effective C++");
    s2 = s1;
} // A

A点でs1死ぬ。refcount が 1 の場合、共有していたストレージがクリーンアップされ、s2無効s2なストレージが使用されます。

参照カウントは各オブジェクトに関連付けられていません。私が示した例からわかるように、クリーンアップしても安全であることを示す指標として参照カウントは決して信頼できないため、それは無意味です。

参照カウントは、それらのオブジェクトが共有するストレージの断片に関連付けられています。との両方の参照カウントは 1 つだけです。この 2 つは、「より効果的な C++」を含むストレージを共有しています。つまり、そのストレージへの参照が 2 つあるということです。2 つのそれぞれが、もう一方が使用しているストレージをクリーンアップしないように、2 つあることを認識する必要があります。s1s2

于 2012-07-15T23:33:14.993 に答える
0

参照カウントは、別の共有メモリに存在する必要があります。

struct Foo
{
    unsigned int * refcount;      // shared among all "equal" objects!

    Foo() : refcount(new auto {1U}) { }

    Foo(Foo const & rhs) : refcount(rhs.refcount) { ++*refcount; }

    ~Foo() { --*refcount; if (*refcount == 0) { delete refcount; } }

    Foo & operator=(Foo const & rhs)
    {
        if (this == std::addressof(rhs)) { return *this; }
        --*refcount;
        if (*refcount == 0) { delete refcount; }
        refcount = rhs.refcount;
        ++*refcount;
        return *this;
    }

    // etc.
};
于 2012-07-15T23:35:25.963 に答える
0

value基になる実装構造体へのポインターです。文字列コピー コンストラクターは、ポインターを新しいオブジェクト ( s2) にコピーし、ポイントされた実装構造体の参照カウントをインクリメントします。ただし、元のオブジェクト ( s1) には同じポインターがあるため、s1 から見た参照カウントもインクリメントされることに注意してください。基になる実装構造体は 1 つしかないため、1 つの String オブジェクトからそれを操作すると、その実装構造体を共有する他のすべての String オブジェクトに影響します。それが参照カウントの要点です!

于 2012-07-15T23:37:58.567 に答える