1

私はそのようなC++コードを持っています(なぜそんなに醜いのか聞かないでください;)-コードのさらに別の部分のために、それは本当に意味があると信じなければなりません):

IntSet temp;
SuperSet superSet;
for (uint i = 0; i < noItems; i++) {
        temp.insert(i);
        superSet.insert(temp);
        temp.clear();
}

noItemsこれは、整数のセット ( IntSet、それぞれが 1 つの整数値を含む)を準備し 、それを他のセット ( SuperSet) に挿入することを目的としています。両方のセットは次のように定義されます。

typedef unsigned int DataType;
typedef std::set<DataType> IntSet;
typedef std::set<IntSet> SuperSet;

temp私にとって、このコードは意図したとおりに動作しないはずです。なぜなら、に挿入した直後に をsuperSetクリアしていて、 がその引数として参照を取得しているtempことがわかったからです: ( http://www.cplusplus.com/reference/stl/セット/挿入/ )insertpair<iterator,bool> insert ( const value_type& x );

したがって、上記のコードの結果として、SuperSetクリアされた のみを含むが得られるはずですIntSet。しかし、「残念ながら」このコードは機能します-すべてIntSetの は適切な値で満たされています...だから私の質問は-STLのセットからの挿入メソッドは実際にその本体で何をしますか? 参照によって渡されたオブジェクトを単にコピーするだけですか? そして、オブジェクト型またはプリミティブ型を渡す間のこのメソッドの動作の違いは何ですか?

回答ありがとうございます。

4

2 に答える 2

1

insert()引数を渡すときにコピーを回避するために、参照引数を取ります。ただし、アイテムをコレクションに保存するときにコピーが作成されます。この場合、clear()が機能するのはこのためです。また、これはどちらの場合にも当てはまります。したがって、「再利用」している場合でもtempsuperSet

于 2012-06-07T22:46:09.207 に答える
0

SuperSet値によるストアの宣言でIntSetあるため、新しい要素を挿入する唯一の方法はコピーを作成することです。コピーが作成されるため、元の変更はコピーにはIntSet反映されません。

これは特にあなたがどのように渡すかに当てはまりますtemp.C superSet++ 11では、あなたの使い方は非効率的になります. 一時変数として使用するローカル変数を宣言することで、強制的にコピーを作成することでムーブ セマンティクスの使用を防ぎます。

SuperSet superSet;

for (DataType i = 0; i < noItems; i++)
{
    superSet.insert(IntSet(&i, &i + 1));
}

割引の最適化では、コンパイラは一時的な要素を作成し、IntSetそれを単一の要素で初期化します。コンパイラはこれが一時的なものであることを認識しているため、移動コンストラクタを使用して値を挿入できます。これにより、IntSet渡されたの浅いコピーが実行され、その値がデフォルト状態 (nullptr へのポインター) にリセットされ、move が発生します。

于 2012-06-08T02:05:20.007 に答える