修改c++ std::set中元素中与排序相关的部分
Modify sort-relevant parts of an element in a C++ std::set
我知道这是有问题的,但我很好奇这样做是否会导致未定义的行为?
class A
{
public:
int i;
};
class As {
public:
bool operator()(const A* l, const A* r)
{
return l->i < r->i;
}
};
int main() {
std::set<A*,As> s;
A* a1 = new A();
a1->i = 9;
A* a2 = new A();
a2->i = 2;
s.insert(a1);
s.insert(a2);
for(std::set<A*,As>::iterator i = s.begin(); i != s.end(); ++i)
std::cout<<(*i)->i<<std::endl;
for(std::set<A*,As>::iterator i = s.begin(); i != s.end(); ++i)
{
if((*i)->i == 2)
(*i)->i = 22;
}
for(std::set<A*,As>::iterator i = s.begin(); i != s.end(); ++i)
std::cout<<(*i)->i<<std::endl;
//now s is in incorrect state, insert all elements into a tmp one
std::set<A*,As> t;
for(std::set<A*,As>::iterator i = s.begin(); i != s.end(); ++i)
t.insert(*i);
s.swap(t);
for(std::set<A*,As>::iterator i = s.begin(); i != s.end(); ++i)
std::cout<<(*i)->i<<std::endl;
}
输出为:
2
9
22
9
9
22
在GCC 4.7编译时似乎工作得很好,但我不知道这是否只是运气。
标准(c++ 11)说明了在关联容器中使用的键比较函数,即std::set
:
(§23.2.4/3)[…对于同一容器中的任意两个键
k1
和k2
,调用comp(k1,k2)
将始终返回相同的值。
这里的comp
指的是比较函数,在你的例子中是函子As()
。
显然,当键包含指向外部对象的指针,并且调用comp(k1,k2)
的结果依赖于这些外部对象时,则修改这些对象会导致违反上述规则。
标准没有说如果你违反了这个规则会发生什么。所以,正式地说,你有未定义的行为(因为标准没有定义行为)。
在实践中,我猜有一个很大的机会,可怕的事情,包括分割错误,可能会发生作为违反的结果,因为下次搜索集的关键字,或插入,搜索算法& & &;建立在键按顺序排列的假设之上& & &;可能会误入歧途,进行越界访问等。
所以结论是,是的,这是UB,即使它在实践中只在少数选定的情况下有效,也可能导致不好的事情发生。
相关文章:
- 查找两个排序向量中共有的元素
- C++ 如何比较n个排序的整数向量以找到互元素?
- 如何在 c++ 中根据第二个元素按降序对列表进行排序
- 对的排序向量 (std::vector<pair<int, int>>) 按对的第一个元素搜索并更新第二个元素值
- 高级选择排序 - 在一次迭代中搜索两个元素
- 为什么用户定义的函数不按照给定的顺序对相同长度的元素进行排序?
- 为什么这个选择排序算法仍然切换一个元素,当它已经是其他元素中最小的元素时?
- 快速排序 - 三个中位数枢轴选择 - 某些元素顺序不正确
- 将一系列已排序的元素划分为相邻组
- 如何通过保持第一个插入的位置来对列表中插入的其余元素进行排序?
- 保持排序的数据结构,允许log N插入时间,并且可以返回我在log N中查找的元素的索引
- "x"的所有元素都存在于"y"(排序向量)中吗?
- 如何根据对的第二个元素对 STL c++ 中的一组对进行排序?
- 如何在保持它们连接到同一元素的同时对 2 个数组进行排序?
- C++:结构与用于排序元素的函数
- 无法在阵列中重新排序元素-rapidjson
- 比较两个向量中的未排序元素
- 我如何在队列中排序元素
- c++中的Hashmap不排序元素
- c++插入排序元素