22. 切勿直接修改set或multiset中的键

本文详细解析了如何安全地修改C++ STL容器set与multiset中的元素,强调了键值不可直接修改的原则,并提供了一种五步法确保修改操作既安全又高效。

像所有的标准关联容器一样,set和multiset按照一定的顺序来存放自己的元素,而这些容器的正确行为也是建立在其原始保存有序的基础之上的。如果把关联容器中的一个元素的值改变了,那么,新的值可能不在正确的位置上,这将会打破容器的有序性。

直接修改map、multimap的值,不能通过编译,因为他们的元素类型实际为std::pair<const K, V>,因为键的类型是const K,所以不能修改。

直接修改map、multimap的键行不通,但是修改set、multiset的键却是可行的。其元素类型为T而非const T。
有一个雇员类;

class Employee
{
public:
	...
	const std::string& name() const;
	void SetName(const std::string& name);
	const std::string& title() const;
	void SetTitle(const std::string& title);
	int idNumber() const;
	...
}

创建一个使用id进行排序的set:

auto sortFunc = [](const Employee& lhs, const Employee& rhs) {return lhs.idNumber() < rhs.idNumber(); };
std::set<Emplyee, sortFunc> datas;

datas以Employee的id进行排序,只要不修改id,datas的排序就不会改变,所以set、multiset的键为T而不是const T。

因为set或multiset中的值不是const,所以,对这些值进行修改的代码可以通过编译。如果你修改set或multiset中的元素,请记住,一定不要改变键部分-元素的这部分信息会影响容器的排序性。如果改变了这部分内容,那么你可能会破坏该容器,再使用该容器将导致不确定的结果,而错误的责任在于你

如果想以一种总是可行而且安全的方式来修改set、muliset、map、multimap中的元素,则可以分5个简单步骤来进行:

  1. 找到你想修改该的容器的元素。
  2. 为将要被修改的元素做一份拷贝。
  3. 修改该拷贝,使它具有你期望它在容器中的值。
  4. 把该元素从容器中删除,通常是通过调用erase来进行的。
  5. 把新的元素从容器中删除,如果按照容器的排列顺序,新元素的位置可能与被删除元素的位置相同或紧邻,则使用“提示hint”形式的insert,以便把插入的效率从对数时间提高到常数时间。

例如,将datas中键为“WorldPeace”的元素修改为“HelloWorld”:

auto iter = datas.find("WorldPeace");
if (iter != datas.end())
{
	auto curData = *iter;
	curData.setName("HelloWorld");
	datas.erase(iter);
	datas.insert(curDatas);
}
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值