区别:
set.insert() set不能有重复值插入
在上一篇学习笔记知道set容器是不允许有重复值插入的,那么具体看看其中的原因。
首先,创建set容器,插入数据,选中insert→右键→转到定义,查看insert的定义
解释:
可以看到insert的返回值是pair类型,即返回值是对组类型,相当于返回值有两个数据,一个是迭代器iterator,表示插入值的位置,另一个是bool类型,表示这个值是否插入成功。对于set的insert而言,返回结果就是这个值是否插入成功,插入成功的话,也会有插入位置。其中,pair就是对组,是一组成对出现的数据。
multiset.insert() 允许有重复值插入
同样地,看看multiset容器中insert()函数是怎么定义的。
首先,创建set容器,插入数据,选中insert→右键→转到定义,查看insert的定义
解释:
在multiset容器中insert的返回值是一个迭代器,没有bool类型的返回值来判断是否重复插入,不像set容器中insert的返回值是pair对组类型。
接下来看看set容器和multiset容器重复插入一个值,insert的返回结果会有什么不一样。
测试代码:
void test1()
{int n = 30;cout << "set.insert() " << endl;set s1;//insert的返回值类型是pair对组类型(成对出现的数据,数据1是迭代器,数据2是bool类型)pair::iterator, bool> result1 = s1.insert(21);if (result1.second)//第二个数据是bool类型{cout << "第一次插入成功" << endl;//返回真 插入成功}else{cout << "第一次插入失败" << endl;}pair::iterator, bool> result2 = s1.insert(21);if (result2.second)//第二个数据是bool类型{cout << "第一次插入成功" << endl;//返回真 插入成功}else{cout << "第一次插入失败" << endl;}cout << string(n, '-') << endl;cout << "multiset.insert() " << endl;multiset s2;s2.insert(23);s2.insert(23);//insert的返回值类型是iterator类型 没有bool类型的返回值判断是否重复插入for (multiset::iterator it = s2.begin(); it != s2.end(); it++){cout << *it << " ";}cout << endl;cout << string(n, '-') << endl;
}
解释:
可以看到在第二次插入值21时,insert第二个返回值是false,插入失败,无法插入重复值。也就是说insert第二个bool类型的返回值是用来检测重复值的,如果插入的是重复值,直接返回false;如果不是重复值,返回true。这很好地体现了set容器中为什么不能插入重复值。在set容器的定义中,如果有重复值插入,会直接返回一个插入失败结果
总结:
功能描述: 成对出现的数据,利用对组可以返回两个数据
两种创建方式:
pair p ( value1, value2 );
pair p = make_pair( value1, value2 );
示例:
void test1()
{int n = 20;cout << "第一种方式" << endl;pair p1("Bella", 56);//类似默认构造 本质是类模板cout << "姓名:" << p1.first << "体重:" << p1.second << endl;//通过 . 访问第一个和第二个数据cout << string(n, '-') << endl;cout << "第二种方式" << endl;pair p2 = make_pair("Bella", 54);cout << "姓名:" << p2.first << "体重:" << p2.second << endl;
}
总结: 两种方式都可以创建对组,记住一种即可
学习目标: set容器默认排序规则为从小到大,掌握如何改变排序规则
主要技术点: 利用仿函数,可以改变排序规则
在之前的学习中,set插入数据时就会对数据进行一个排序,并且默认的排序规则是从小到大。那么如何改变这个排序规则呢?
class myCompare
{
public:bool operator()(int value1, int value2) const{return value1 > value2;}
};void test1()
{set s1;s1.insert(21);s1.insert(22);s1.insert(23);s1.insert(24);s1.insert(25);cout << "默认排序规则为从小到大 s1:";for (set::iterator it = s1.begin(); it != s1.end(); it++){cout << *it << " ";}cout << endl;set s2;s2.insert(21);s2.insert(22);s2.insert(23);s2.insert(24);s2.insert(25);cout << "指定排序规则为从大到小 s2:";for (set::iterator it2 = s2.begin(); it2 != s2.end(); it2++){cout << *it2 << " ";}cout << endl;
class Person
{
public:Person(string name, int age, int height, int weight){this->m_name = name;this->m_age = age;this->m_height = height;this->m_weight = weight;}string m_name;int m_age;int m_height;int m_weight;
};class myCompare
{
public:bool operator()(const Person&p1, const Person&p2) const{if (p1.m_age == p2.m_age){return p1.m_height > p2.m_height;}else if (p1.m_height == p2.m_height){return p1.m_weight < p2.m_weight;}else{return p1.m_age > p2.m_age;}}
};void test1()
{//创建人物set s;string nameseed[] = { "张飞", "孙权", "西施", "貂蝉", "王昭君", "关羽" };int ageseed[] = { 28, 28, 25, 24, 26, 28 };int heightseed[] = { 178, 170, 153, 153, 153, 200 };int weightseed[] = { 140, 135, 108, 95, 100, 165 };for (int i = 0; i < 6; i++){Person p(nameseed[i], ageseed[i], heightseed[i], weightseed[i]);s.insert(p);}cout << "自定义数据类型 set" << endl;for (set::iterator it = s.begin(); it != s.end(); it++){cout << "姓名:" << it->m_name << "\t年龄:" << it->m_age<< "\t身高:" << it->m_height << "\t体重:" << it->m_weight << endl;}cout << endl;
}
注意点
set st;
,参数类型是类模板,因此这个仿函数也封装在类中;bool operator()(int v1, int v2) { }
。如果set插入的数据是自定义数据类型Person, 那么仿函数的形参也应该是Person类型,即bool operator()(const Person& v1, const Person& v2) { }
,这里加入const修饰,防止数据类修改;使用引用防止浅拷贝。set::iterator
,set::iterator
总结:
对于内置数据类型,利用仿函数可以指定set容器的排序规则即可;
对于自定义数据类型,set必须指定排序规则才可以插入数据。
下一篇:qt没有mysql驱动的解决办法