1

次のプログラムを検討してください。intへのポインタのセットを作成し、指定された整数の値でセットをソートするカスタムindrect_lessコンパレータを使用します。これが完了したら、ポイントされた整数の1つの値を変更します。次に、セットの順序がソートされなくなったことがわかります(セットは何かが変更されたことを認識していないためだと思います)。

(C ++ 0xループを気にしないでください、私はVS2010で実行しています)

#include <iostream>
#include <set>
using namespace std;

struct indirect_less {
    bool operator()(int* l, int* r) const
    {
        return *l < *r;
    }
};

int main()
{
    set<int*, indirect_less> myset;

    int* a = new int(5);
    int* b = new int(6);
    int* c = new int(7);

    myset.insert(a);
    myset.insert(b);
    myset.insert(c);

    cout << "Set contains: ";
    // (outputs: 5 6 7)

    for (auto i = myset.begin(), end = myset.end(); i != end; ++i)
    {
        cout << **i << " ";
    }

    cout << endl << "Modifying *a" << endl;
    *a = 9;         // point of interest
    cout << "Set contains: ";
    // (outputs: 9 6 7 - unsorted order)

    for (auto i = myset.begin(), end = myset.end(); i != end; ++i)
    {
        cout << **i << " ";
    }

    cout << endl;

    cin.get();

    return 0;
}

1)未定義動作を呼び出しているのは正しいですか?行の後に全体の状態がmyset無効*a = 9;ですか?

2)これを消去してから再挿入する唯一の正しい方法はありaますか?

3)一度*a = 9;実行された後、明確に定義された動作で、セットをソートされた順序にリバランスする方法はありますか?

4

3 に答える 3

2

はい、std::set要素は不変であると想定しています。危険な場合は、変更するたびに自分で並べ替えることができます。ただし、お勧めしません。別のコレクションタイプを使用してください。

于 2010-08-10T16:50:14.220 に答える
1

1)はい、setはその要素の変更を許可しません。

2)古い値を削除して新しい値を挿入するだけでなく、古いセットを新しく作成したセットに置き換えることもできます。

3)いいえ

于 2010-08-10T16:54:25.533 に答える
1

1)動作が未定義であることを知りません。この例の追加のひねりは、セットの要素が変更されないことです。セットの各要素はポインターです。'* a = 9 "の行を実行する前後で、セットの(ポインター)要素を印刷すると、ポインターの値が割り当ての前後で同じ順序になっていることがわかると思います。変更点は次のとおりです。 1つのセット要素が指す値。これはセットの後援の外で行われたため、セットには希望する順序を維持する方法がありません。

2)資格のある「はい」。これにより、indirect_less()を使用してセットの要素を並べ替えることができます。繰り返しになりますが、セットの要素であるポインターを、逆参照された各ポインターの値で並べ替えていることに注意してください。しかし、あなたが説明したまさにその理由から、これはやや危険だと私は思います。

印刷出力の「Setcontains:」という凡例から、この例は整数のセットを形成しようとしていると思います。ただし、定義されたセット、つまり「セット」は、実際には整数自体ではなく、整数へのポインターで構成されます。望ましいコレクションと実際のコレクションの間のこの不整合が、問題の根本的な原因であると私は信じています。

3)2)を参照してください。

于 2010-08-10T17:33:42.290 に答える