gpt4 book ai didi

c++ - 修改 C++ std::set 中元素的排序相关部分

转载 作者:行者123 更新时间:2023-11-30 02:54:45 25 4
gpt4 key购买 nike

我知道这是有问题的,但我很好奇这样做是否会导致未定义的行为?

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) [...] For any two keys k1 and k2 in the same container, calling comp(k1,k2) shall always return the same value.

comp 指的是比较函数,在您的例子中是仿函数 As()

显然,当键包含指向外部对象的指针并且调用 comp(k1,k2) 的结果取决于这些外部对象时,修改对象会导致违反上述规则。

标准没有说明如果您违反此规则会发生什么。所以,正式来说,你有未定义的行为(因为标准没有定义行为)。

在实践中,我猜很可能由于违规而发生可怕的事情,包括段错误,因为下一次在集合中搜索键或进行插入时,搜索算法——建立在 key 有序的假设之上——可能会误入歧途并进行越界访问等。

所以结论是,是的,这就是 UB,即使在实践中它在一些选定的情况下有效,也可能导致坏事发生。

关于c++ - 修改 C++ std::set 中元素的排序相关部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16870557/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com