通过间接使指针集无效

时间:2010-08-10 16:30:22

标签: c++ set undefined-behavior

考虑以下计划。它创建了一组指向内部的指针,并使用一个自定义的indrect_less比较器,它通过指向整数的值对集合进行排序。完成后,我然后更改其中一个指向整数的值。然后,可以看出集合的顺序不再排序(我想因为集合不知道某些事情发生了变化)。

(不介意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;后,有没有办法重新平衡有关排序顺序的集合,具有明确定义的行为?

3 个答案:

答案 0 :(得分:2)

是的,std::set假定元素是不可变的。 possible,如果有危险,可在每次更改后自行重新排序。但我不推荐它:使用另一种集合类型。

答案 1 :(得分:1)

1)是的,set不允许修改它的元素。

2)除了删除旧值并插入新值外,您还可以用新构造的值替换旧值。

3)否

答案 2 :(得分:1)

1)我不知道行为是未定义的。此示例中的附加扭曲是集合的元素不会更改 - 集合中的每个元素都是指针。如果你在执行'* a = 9'之前和之后打印出集合的(指针)元素,我相信你会发现在赋值之前和之后指针值的顺序相同。改变的是一个集合元素指向的值。这是在集合的主持之外发生的,因此集合无法维持你想要的顺序。

2)合格的“是”。这将强制使用indirect_less()来对集合的元素进行排序。再次,请注意您通过每个解除引用的指针的值来排序集合的元素,指针。然而,正如你所描述的那样,这对我来说有些冒险。

从打印输出中的图例“Set contains:”,我假设这个例子努力形成一组整数。但是,定义的集合,即“set”实际上由指向整数的指针组成,而不是整数本身。我认为,期望和实际集合之间的这种不对齐是问题的根本原因。

3)见2)。