上一个程序初步简单的实现了使用自定义operator的方式的map的初始化,但是遇到了一个问题:
检查operator函数时报“invalid operator<”错误,程序崩了。下午找出原
因。下一个程序中解决该问题,并实现高内聚。
“invalid operator<”错误的原因是(具体见这里):
在待排序列中如果出现相等元素,则会报错Expression : invalid operator <
原因是,c++编译器检测到调用cmp的参数a==b时,c++编译器会立即用反序参数调用cmp函数,即调用cmp(b,a),来判断cmp函数是否已经执行了严格的弱序规则(a与b相等则位置不被改变)
于是,重新实现operator中的条件判断及返回值,这两点就是解决问题的关键。调试通过,程序能正常运行。
// Practice6_map_sort_by_comparator.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <map>
#include <string>
#include <iostream>
using namespace std;
typedef struct tagStudentInfo
{
int stuId;
string stuName;
}StudentInfo;
/* 两种方式实现操作符函数,一种是struct,另一种是class加public
struct CompareStu
{
int operator()(const StudentInfo &x, const StudentInfo &k) const
{
if(k.stuId > x.stuId) return 1;//这里必须是大于,并且return true,原因见参考链接
else return x.stuName.compare(k.stuName) > 0;
}
};*/
/* 另一种是class加public
class CompareStu
{
public:
int operator()(const StudentInfo &x, const StudentInfo &k) const
{
if(k.stuId > x.stuId) return 1;//这里必须是大于,并且return true,原因见参考链接
else return x.stuName.compare(k.stuName) > 0;
}
};*/
/* 上面的两种实现在使用for循环insert数据时是有问题的,主要在于两元素相等时的返回值,下面这种可编译通过*/
class CompareStu
{
public:
int operator()(const StudentInfo &x, const StudentInfo &k) const
{
if(k.stuId != x.stuId)
return k.stuId > x.stuId;//这里必须是大于,并且return true,原因见参考链接
else
return k.stuName.compare(x.stuName) > 0;
}
};
/* 第一种初始化方式*/
void initMap( map<StudentInfo, int, CompareStu> &mapStu)
{
StudentInfo studentInfo;
studentInfo.stuId = 1;
studentInfo.stuName = "student_one";
mapStu.insert(pair<StudentInfo, int>(studentInfo, 90));
studentInfo.stuId = 2;
studentInfo.stuName = "student_two";
mapStu.insert(pair<StudentInfo, int>(studentInfo, 80));
}
string strs[5] = {"iphone", "xiaomi", "meizu", "oppo", "vivo"};
/* 第二种初始化方式*/
void initMapByPair(map<StudentInfo, int, CompareStu> &mapStu, unsigned int size)
{
StudentInfo si = {0, ""}; //两种方式实现StudentInfo的初始化,一种是先声明后赋值,另一种直接在循环中初始化。不能混用!!为啥??
for(unsigned int i = 0; i < size; i++)
{
si.stuId = i + 1;
si.stuName = strs[i];
mapStu.insert(pair<StudentInfo, int>(si, i + 90));
}
}
void printMap(map<StudentInfo, int, CompareStu> mapStu)
{
map<StudentInfo, int, CompareStu>::iterator iter= mapStu.begin();
for(; iter != mapStu.end(); iter++)
{
cout << iter->first.stuId << "," << iter->first.stuName << "," << iter->second << endl;
}
}
int main()
{
map<StudentInfo, int, CompareStu> mapStudent;
//initMap(mapStudent);
initMapByPair(mapStudent, 5);//第二种初始化方式
printMap(mapStudent);
}
运行结果:
1,iphone,90
2,xiaomi,91
3,meizu,92
4,oppo,93
5,vivo,94