语言的哪一部分禁止更改 std::set 的元素
Which part of the language forbids changing elements of an std::set
std::set
是一个排序的关联容器,可以快速查找其元素。键以排序方式插入,键一旦插入就无法修改以保留该顺序。
考虑以下演示,该演示构造了int*
的std::set
,然后尝试中断其元素的排序:
#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
的大部分其他功能。
代码显然有问题。据我所知,它遵循所有语言规则,我似乎没有违反我可以找到的比较功能或set
的任何要求。但是set
提供的保证仍然被打破了,这意味着我一定错过了什么。
在 C++17 中,有 [associaciative.reqmts]/3:
。对于同一容器中
k1
和k2
的任何两个键,调用comp(k1, k2)
应始终返回相同的值。
因此,您的代码具有 UB,因为它违反了此要求。
[不是很政治正确的评论:很多东西在标准中是不成文的,甚至写的东西有时也是不正确的。你必须弥补缺失的部分,这比解析确切的单词更可靠。
所有关联容器(已排序或未排序(均基于公理化要求。
隐含的基础是,所有有公理的谓词/函子都是数学关系/函数,否则公理可能没有任何意义。所以很明显,这些函数,如比较器,必须很好地定义;这意味着当前在容器中的元素是有序的。
但是,如果您的容器是空的并且您更改了其排序功能,这并不重要。您还可以使用极坐标排序,根据角度对元素进行排序,使用任意截止值(根据定义,最小角度(,如果旋转未经过容器中的元素,则旋转该最小角度线。
相关文章:
- 使用std::transform将一个范围的元素添加到另一个范围中
- 有没有办法将谓词中的元素偏移量传递给 std 算法?
- 我想访问std::unique_ptr中的一个特定元素
- 如何从存储在std::映射中的std::集中删除元素
- 缓存std::数组的选定元素,并在c++中自动保持其一致性
- 从嵌套在std::映射中的std::列表中删除元素的最佳方式
- 使用运算符 [] 引用 std::vector 上最后一个元素时出现问题<>
- 对的排序向量 (std::vector<pair<int, int>>) 按对的第一个元素搜索并更新第二个元素值
- 为什么在 std::map 上移动无法将元素从一个映射移动到另一个映射
- 如何为 std::vector 分配内存,然后稍后为某些元素调用构造函数?
- std::矢量保存 只推送最后一个元素
- std::map:当元素不可默认构造时创建/替换元素
- 如何读/写或遍历 std::array 中的特定元素范围?
- C++如何乘以包含 std::variant 元素的向量的迭代器?正在执行迭代器类型的转换?
- 为什么 std::p air 的大小与其元素的大小之和不同?
- 我可以列表初始化 std::vector 并完美转发元素吗?
- 使用 std::min_element、std::max_element 查找矢量中的最小和最大元素
- 是否有一个 std::set 函数来确定不超过数字 x 的最大元素?
- 除了 std::vector 之外,是否有一个 std 容器不会复制和销毁作为类的元素?
- call call cons构件功能的std ::元素的每个元素