std::map、std::set使用自定义数据的键值时注意排序

本文介绍了在C++中使用自定义数据类型作为map或set的key时,如何解决排序问题的四种方法:1) 重载`operator<()`;2) 自定义比较函数对象;3) 使用`std::function`封装比较函数;4) 特化`std::less`模板。通过这些方法,可以确保自定义类型在容器中的正确排序和查找。

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

map、set插入自定义数据类型作为key时需要注意什么问题问题?!!!!!!!!
首先要解决排序问题,方法有:
1.重载自定义数据类型的operator<()操作符

2.map类型的第三个参数为函数对象类类型,可以自定义这个比较函数的函数对象,
  如申明一个类似
  struct CustomLess
  {
      bool operator()(const CustomKey2& other1, const CustomKey2& other2)
      {
      return other1.a < other2.a || (other1.a == other2.a && other1.b < other2.b);
      }
  };
  的函数对象,将其作为map申明类型的第三个参数类型传入

3.利用std::function封装一个
  typedef std::function<bool(const CustomKey2&, const CustomKey2&)> FuncType;
  将FuncType作为map的第三个参数,并在定义map对象时传入一个FuncType的可执行体,如对对应的普通函数指针,函数对象,Lambda表达式等

4.对map的第三个参数类型less函数的进行模板定制-可以全特化
  模板特化匹配优先级:全特化 > 偏特化 > 主模板

#include <map>
#include <string>
#include <iostream>
#include <functional>

using namespace std;

/************************************************************************/
/* 
map、set插入自定义数据类型作为key时需要注意什么问题问题?!!!!!!!!
首先要解决排序问题,方法有:
1.重载自定义数据类型的operator<()操作符

2.map类型的第三个参数为函数对象类类型,可以自定义这个比较函数的函数对象,
  如申明一个类似
  struct CustomLess
  {
	  bool operator()(const CustomKey2& other1, const CustomKey2& other2)
	  {
	  return other1.a < other2.a || (other1.a == other2.a && other1.b < other2.b);
	  }
  };
  的函数对象,将其作为map申明类型的第三个参数类型传入

3.利用std::function封装一个
  typedef std::function<bool(const CustomKey2&, const CustomKey2&)> FuncType;
  将FuncType作为map的第三个参数,并在定义map对象时传入一个FuncType的可执行体,如对对应的普通函数指针,函数对象,Lambda表达式等

4.对map的第三个参数类型less函数的进行模板定制-可以全特化
  模板特化匹配优先级:全特化 > 偏特化 > 主模板
*/
/************************************************************************/

/*
std::map类型的定义头部模板参数

template<class _Kty,
class _Ty,
class _Pr = less<_Kty>,
class _Alloc = allocator<pair<const _Kty, _Ty> > >

第1个参数存储了key。
第2个参数存储了mapped value。
第3个参数是比较函数的函数对象。map用它来判断两个key的大小,并返回bool类型的结果。利用这个函数,map可以确定元素在容器中遵循的顺序以及两个元素键是否相等(!comp(a,b)&&!comp(b,a)),确保map中没有两个元素可以具有等效键。这里,它的默认值是less<Key>,定义如下

std::map的部分构造函数:

map()
: _Mybase(key_compare())
{	// construct empty map from defaults
}

// 入参时比较函数或对象
explicit map(const key_compare& _Pred)
: _Mybase(_Pred)
{	// construct empty map from comparator
}

// map默认比较函数对象 less<_Kty>
template<class _Ty = void>
	struct less
	{	// functor for operator<
	typedef _Ty first_argument_type;
	typedef _Ty second_argument_type;
	typedef bool result_type;

	constexpr bool operator()(const _Ty& _Left, const _Ty& _Right) const
	{	// apply operator< to operands
	return (_Left < _Right);
	}
	};

*/

// 自定义数据key
struct CustomKey1
{
	CustomKey1()
	{}

	CustomKey1(int ai, int bi): a(ai), b(bi)
	{}

	// 方法1,重写<操作符
	bool operator<(const CustomKey1& other) const // 注意这里的两个const
	{
		return a < other.a || (a == other.a && b < other.b);
	}

	int a = 1;
	int b = 2;
};

// 测试重载<操作符
void Test_Operator_CustomKey1()
{
	std::map<CustomKey1, int> mapCustomKeyInt;
	mapCustomKeyInt.insert(std::make_pair(CustomKey1(1, 2), 1));
	mapCustomKeyInt.insert(std::make_pair(CustomKey1(1, 3), 1));
}

struct CustomKey2
{
	CustomKey2()
	{}

	CustomKey2(int ai, int bi) : a(ai), b(bi)
	{}

	int a = 1;
	int b = 2;
};

// 2.将map类型的第三个参数函数对象类型重写
struct CustomLess
{
	bool operator()(const CustomKey2& other1, const CustomKey2& other2)
	{
		return other1.a < other2.a || (other1.a == other2.a && other1.b < other2.b);
	}
};

// 将map类型的第三个参数函数对象类型重写
void Test_CustomLess()
{
	std::map<CustomKey2, int, CustomLess> mapCustomKeyInt;
	/*CustomLess c;
	std::map<CustomKey2, int, CustomLess> mapCustomKeyInt(c);*/ // 也可以传入CustomLess这个可执行对象
	mapCustomKeyInt.insert(std::make_pair(CustomKey2(1, 2), 1));
	mapCustomKeyInt.insert(std::make_pair(CustomKey2(1, 3), 1));
}

// 3.使用std::function 将 一个可以比较的函数或函数对象打包生成一个可调用对象
bool CompareFunc(const CustomKey2& other1, const CustomKey2& other2) // 普通函数
{
	return other1.a < other2.a || (other1.a == other2.a && other1.b < other2.b);
}

void Test_CompareFunc()
{
	typedef std::function<bool(const CustomKey2&, const CustomKey2&)> FuncType;
	std::map<CustomKey2, int, FuncType> mapCustomKeyInt(CompareFunc);
	mapCustomKeyInt.insert(std::make_pair(CustomKey2(1, 2), 1));
	mapCustomKeyInt.insert(std::make_pair(CustomKey2(1, 3), 1));
}

//4.全特化map默认的比较函数对象less
template<>
struct std::less <CustomKey2>
{	// functor for operator<
	bool operator()(const CustomKey2& other1, const CustomKey2& other2) // 普通函数
	{
		return other1.a < other2.a || (other1.a == other2.a && other1.b < other2.b);
	}
};

void Test_less()
{
	std::map<CustomKey2, int> mapCustomKeyInt;
	mapCustomKeyInt.insert(std::make_pair(CustomKey2(1, 2), 1));
	mapCustomKeyInt.insert(std::make_pair(CustomKey2(1, 3), 1));
}

int main()
{
	Test_Operator_CustomKey1();
	Test_CustomLess();
	Test_CompareFunc();
	Test_less();

	getchar();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值