关于set元素的不可直接更改

博客指出set的元素类型和比较函数配置后不可更改,直接修改元素需先删后添以维护有序性。单独修改比较函数或元素数值可能破坏有序性,若同时修改且保证有序则不会。作者因特殊情况修改STL源码生成新类,认为这是STL set类的缺陷。

set的元素类型和比较函数(或者函数对象)是可以配置的,但是一旦配置就不能更改。

set的元素类型不可更改是很自然的,这本就是模板的天然含义。

set的比较函数虽然可以得到,但是得到的是copy,不是引用或者指针,所以不能修改(修改比较函数对象的参数)。

set里面的元素不能直接的更改,一般的做法是先删除旧元素,然后添加新元素,这当然是为了维护里面元素的有序性。

单独的修改set的比较函数和元素数值,都有可能破坏set的有序性,从而破坏set的概念完整性,引起set的非预期行为。但是,从一个特殊的角度看,如果同时修改set的比较函数和元素数值,而且还能保证set内部元素的有序性,这不会破坏set的概念完整性,也不会引起任何的非预期行为。

我最近设计一个算法,正好发生在这种特殊的情况下,不得已只得修改STL的源码生成新的类(我命名为flexible_set),我觉得这是STL set类(也包括map,multiset,multimap)的一个缺陷。

概括起来,我得意思是:

1 修改比较函数

可以这样得到set的比较函数
key_compare kc = set_obj.key_comp();
但是我想这样得到
key_compare& kc = set_obj.key_comp();
然后调用kc的函数设置其参数。我说的修改比较函数就是这个意思

2 修改值

iterator it = set_obj.begin();

*it = 3;

在C++中,`std::set` 是一种关联容器,它存储唯一的、排序的元素。由于 `std::set` 的内部实现依赖于其元素的排序规则(通常是基于平衡二叉树),因此直接修改 `set` 中的元素可能会破坏容器的排序结构,导致未定义行为。 ### 问题产生的原因: 1. **排序规则**:`std::set` 中的元素是按照特定的顺序排列的(默认为升序)。如果直接修改某个元素,可能会改变该元素在排序中的位置,从而破坏容器的内部结构。 2. **键值不可变性**:`std::set` 中的元素实际上是作为“键”来使用的,而键值在插入后能被修改。如果允许修改键值,可能导致容器无法正确维护其排序和唯一性约束。 ### 示例代码(尝试修改 `std::set` 中的元素): ```cpp #include <iostream> #include <set> int main() { std::set<int> mySet = {1, 2, 3, 4, 5}; // 尝试使用非常量引用遍历并修改 set 中的元素 for (auto& elem : mySet) { // elem *= 2; // 错误:直接修改 set 中的元素 } return 0; } ``` ### 解释: - 在上面的代码中,`for (auto& elem : mySet)` 使用了非常量引用遍历 `mySet`。然而,`std::set` 中的元素实际上是常量的,编译器会阻止对这些元素修改。 - 如果尝试通过迭代器或其他方式修改 `set` 中的元素,会导致编译错误或未定义行为。 ### 正确的修改方法: 如果需要修改 `std::set` 中的某个元素,必须先删除该元素,然后插入新的值。以下是正确的做法: ```cpp #include <iostream> #include <set> int main() { std::set<int> mySet = {1, 2, 3, 4, 5}; // 查找要修改元素 auto it = mySet.find(3); if (it != mySet.end()) { int newValue = *it * 2; // 计算新值 mySet.erase(it); // 删除旧值 mySet.insert(newValue); // 插入新值 } // 输出修改后的 set for (const auto& elem : mySet) { std::cout << elem << " "; } std::cout << std::endl; return 0; } ``` ### 解释: 1. **`auto it = mySet.find(3);`**:查找值为 `3` 的元素。 2. **`mySet.erase(it);`**:删除找到的元素。 3. **`mySet.insert(newValue);`**:插入计算后的新值。 4. 这种方法确保了 `std::set` 的排序规则会被破坏。 ### 注意事项: - `std::set` 中的元素是唯一的,插入新值时会自动检查是否存在重复值。 - 如果需要频繁修改元素,可以考虑使用其他容器(如 `std::vector` 或 `std::unordered_set`),或者使用 `std::multiset`(允许多个相同元素)。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值