std::set
是排序后的关联容器,可快速查找其元素。密钥以一种排序的方式插入,一旦插入就不能修改密钥以保持该顺序。
考虑以下示例,该示例构造std::set
的int*
,然后尝试破坏其元素的排序:
#include <iostream>
#include <set>
int values[] = { 50, 40, 30, 20, 10 };
// Comparator that sorts by pointed value
struct comparator {
bool operator()(const int* left, const int* right) const {
return *left < *right;
}
};
using my_set_t = std::set<int*, comparator>;
// Checks if each of the elements of `values` are in the set
void output(const my_set_t & foo)
{
for (auto & x : values) {
std::cout << x << ' ' << foo.count(&x) << '\n';
}
std::cout << std::endl;
}
int main()
{
// Insert the address of each element of `values` into the set
my_set_t foo;
for (auto & x : values) {
foo.emplace(&x);
}
output(foo);
// Changing `values[1]` to zero should break the sorting of the set
values[1] = 0;
output(foo);
}
我得到的输出是:
50 1
40 1
30 1
20 1
10 1
50 1
0 0
30 0
20 0
10 0
表达式
values[1] = 0;
有效地间接更改了set
的键之一。这破坏了顺序,因此似乎也破坏了count
。我认为这也会破坏set
的其他大多数功能。代码显然有问题。据我所知,它遵循所有语言规则,并且似乎没有违反我可以为compare函数或
set
找到的任何要求。但是set
提供的保证仍然是无效的,这意味着我一定错过了一些东西。 最佳答案
在C++ 17中,有[associative.reqmts] / 3:
因此,您的代码具有UB,因为它违反了此要求。