stl::map 重载 operator“<”注意事项

本文介绍了STL中的map容器,它使用一对一的哈希存储数据,并通过红黑树保持数据有序。当map的关键字为自定义类型时,必须重载"<"运算符以支持排序。文中给出了一个struct indices的示例,展示了如何正确重载"<",确保在比较时逻辑严密,避免排序错误。理解并正确实现这个运算符对于使用map存储自定义类型至关重要。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、首先明确map定义

map是STL的一个关联容器,它提供一对一的hash。

  • 第一个可以称为关键字(key),每个关键字只能在map中出现一次;
  • 第二个可能称为该关键字的值(value);

二、注意事项

如果定义的map的关键字(key)是标准库中的类型如(int)(double)(string)等等,则无需重载“<”;

如果定义的map的关键字(key)是自己定义的 结构/类 对象,则注意要重载“<”。

struct indices{ unsigned int v, vt; }
map<indices,int> indicesMap;

如下图:


struct indices
{
	unsigned int v, vt;
	bool operator<(const struct indices & right)const   //重载<运算符
	{
			if (this->vt < right.vt)
				return true;
			else if (this->vt == right.vt)
			{
				if (this->v < right.v)
					return true;	
			}
			return false;
	}
};

1.为什么?

因为map內部的实现自建一颗红黑树,这颗树具有对数据自动排序的功能。在map内部所有的数据都是有序的。比如一个班级中,每个学生的学号跟他的姓名就存在著一对一映射的关系。所以如果不对自定义对象重载“<”函数,会导致map无法完成自动排序,程序会报错:

2.怎么办?

逻辑很简单,只需要定义一个逻辑严密的" operator<"函数即可。

逻辑严密是指在自定义对象的任何情况下,都有唯一的大小比较结果。而且不会出现

a<b,b<c ,而c<a的情况。

代码如下:


struct indices
{
	unsigned int v, vt;
	bool operator<(const struct indices & right)const   //重载<运算符
	{
			if (this->vt < right.vt)
				return true;
			else if (this->vt == right.vt)
			{
				if (this->v < right.v)
					return true;	
			}
			return false;
	}
};

 

 

### C++ 中 `std::unordered_map` 的序列化解决方案 在 C++ 标准库中,`std::unordered_map` 并未提供内置的 `serialize` 方法。因此,在尝试调用此类方法时会引发编译错误[^1]。 为了实现 `std::unordered_map` 的序列化功能,可以借助第三方库(如 **Boost.Serialization**),或者手动编写序列化的逻辑来处理键值对的数据存储与恢复过程。 以下是两种常见的解决方案: --- #### 方案一:使用 Boost.Serialization 实现序列化 通过引入 Boost 库中的 `boost::serialization` 功能模块,能够轻松完成复杂数据结构(包括 `std::unordered_map`)的序列化操作[^2]。 下面是一个完整的代码示例,展示如何利用 Boost 进行序列化和反序列化: ```cpp #include <iostream> #include <fstream> #include <unordered_map> #include <vector> #include <string> // 引入 Boost Serialization 头文件 #include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> #include <boost/serialization/unordered_map.hpp> #include <boost/serialization/vector.hpp> using namespace std; struct SerializableMap { typedef unordered_map<unsigned int, vector<unsigned int>> MapType; MapType data; template<class Archive> void serialize(Archive &ar, const unsigned int version) { ar & data; // 使用 Boost 自动序列化机制 } }; void saveToFile(const SerializableMap& smap, const string& filename) { ofstream ofs(filename); boost::archive::text_oarchive oa(ofs); oa << smap; } SerializableMap loadFromFile(const string& filename) { ifstream ifs(filename); boost::archive::text_iarchive ia(ifs); SerializableMap smap; ia >> smap; return smap; } int main() { SerializableMap smap; smap.data[1] = {10, 20}; smap.data[2] = {30, 40}; saveToFile(smap, "data.txt"); auto loadedSmap = loadFromFile("data.txt"); for (const auto& pair : loadedSmap.data) { cout << "Key: " << pair.first << ", Values: "; for (auto val : pair.second) { cout << val << " "; } cout << endl; } return 0; } ``` 上述代码展示了如何将 `std::unordered_map` 数据保存到文件并从中读取回来的过程。注意需要显式声明模板特化支持以启用 Boost 对 STL 容器的支持。 --- #### 方案二:手动实现序列化逻辑 如果不想依赖外部库,则可以通过流操作符重载的方式自行设计序列化函数。这种方法更加灵活但也更繁琐。 以下是一段简单的例子说明如何手动序列化一个 `std::unordered_map<int, double>` 类型的对象: ```cpp #include <iostream> #include <unordered_map> #include <sstream> #include <iomanip> template<typename KeyT, typename ValueT> std::ostream& operator<<(std::ostream& os, const std::unordered_map<KeyT, ValueT>& umap) { size_t size = umap.size(); os.write(reinterpret_cast<const char*>(&size), sizeof(size)); for (const auto& kv : umap) { os.write(reinterpret_cast<const char*>(&kv.first), sizeof(KeyT)); os.write(reinterpret_cast<const char*>(&kv.second), sizeof(ValueT)); } return os; } template<typename KeyT, typename ValueT> std::istream& operator>>(std::istream& is, std::unordered_map<KeyT, ValueT>& umap) { size_t size; is.read(reinterpret_cast<char*>(&size), sizeof(size)); umap.clear(); for (size_t i = 0; i < size; ++i) { KeyT key; ValueT value; is.read(reinterpret_cast<char*>(&key), sizeof(KeyT)); is.read(reinterpret_cast<char*>(&value), sizeof(ValueT)); umap.emplace(key, value); } return is; } int main(){ std::unordered_map<int, double> myMap{{1, 2.7}, {2, 3.8}}; std::ostringstream oss; oss << myMap; std::istringstream iss(oss.str()); std::unordered_map<int, double> newMap; iss >> newMap; for(auto &[k,v] : newMap){ std::cout<< k << ": "<< v << "\n"; } return 0; } ``` 此方式适用于基本类型的键值组合场景;对于复杂的自定义类型则需额外考虑其内部成员变量的具体情况[^3]。 --- ### 总结 当遇到无法直接访问 `std::unordered_map` 成员函数 `serialize` 的问题时,可以选择集成成熟的第三方工具链(例如 Boost),也可以自己构建基础版的序列化解码流程。具体采用哪种策略取决于项目需求以及开发环境约束条件等因素影响下的权衡结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值