<C++>快速掌握set 容器|去重的底层原因|使用仿函数定义排序规则(下)

简介: <C++>快速掌握set 容器|去重的底层原因|使用仿函数定义排序规则

2、set 和 multiset 插入数据特点不同的原因

上面提到二者的不同点在于是否可以插入不同的数据,那么就来看看二者insert插入方法的源码


2.1、set 中的insert 源码分析

查看set 中的insert 源码:

0e2285f0026e4213a2ce2f0fdf191539.png



可以看到这里的insert返回值类型是一个pair二元组,包含迭代器类型和布尔类型

那么再进行插入操作的时候,如果检查到容器中已经有相同元素,就会返回false,不进行插入

有关二元组的创建将在下面解释

2.2、pair 对组的创建及使用

功能描述:


成对出现的数据,利用对组可以返回两个数据

两种创建方式:


pair<type, type> p ( value1, value2 );

pair<type, type> p = make_pair( value1, value2 );

代码示例:

// pair 对组的使用 make_pair()
void testPair() {
  // 默认构造
  pair<string, int> pre("微凉", 10);
  pair<string, int> ptr = make_pair("秋意", 24);
  // 获取值
  cout << pre.first << ptr.first << "\n" << pre.second << ptr.second << endl;
}

6231509ef11f4c6a9220da9e4a5d9054.png


推荐使用make_pair的方式创建二元组,这样看起来比较清晰

二元组通过调用first和second来访问对应的属性值

2.3、multiset 中的insert 源码分析

查看multiset 中的insert 源码:


6af71603ce3140d18969f0eb2547be08.png


multiset 中的insert 返回值类型是一个迭代器,并没有布尔类型

所以可以插入重复数据

3、内置与自定义数据类型的排序规则

set 容器插入时默认自动升序排序,那么怎么修改排序规则呢:

使用仿函数来指定排序规则

3.1、内置数据类型的排序

写一个类,重载类内的函数运算符() :

// 修改 set 容器的排序规则
class Cmp {
public:
  bool operator()(int v1,int v2) const
  {
    return v1 > v2;
  }
};
void test7() {
  // 默认是升序
  set<int> s1;
  s1.insert(1);
  s1.insert(0);
  s1.insert(2);
  s1.insert(4);
  printSet(s1);
  // 修改为降序,借助仿函数
  set<int, Cmp> s2;
  s2.insert(1);
  s2.insert(0);
  s2.insert(2);
  s2.insert(4);
  for (auto it = s2.begin(); it != s2.end(); it++) {
    cout << *it << " ";
  }
}

要注意的是重载的函数需要是常函数,要加上const关键字

重载的细节可以参考我这篇博客:详解重载函数调用运算符

创建set 容器的时候就要指定排序规则,在尖括号中这样表示:set<int, Cmp>

3.2、自定义数据类型的排序

set 容器插入自定义数据的时候如果不指定排序规则,默认的升序排序也无法进行,因此需要事先指定排序规则:

// 定义Person 类
class Person {
  int age;
  string name;
public:
  Person(string name, int age) {
    this->name = name;
    this->age = age;
  }
  int getAge() const {
    return this->age;
  }
  string getName() const {
    return this->name;
  }
};
// 自定义排序规则
class Compare {
public:
  bool operator()(const Person &p1, const Person &p2)const {
    return p1.getAge() > p2.getAge();
  }
};
void test8() {
  set<Person, Compare> s;
  Person p1("叶落", 20);
  Person p2("微凉", 24);
  Person p3("秋意", 22);
  Person p4("秋白", 18);
  s.insert(p1);
  s.insert(p2);
  s.insert(p3);
  s.insert(p4);
  for (auto it = s.begin(); it != s.end(); it++) {
    cout << "姓名:" << it->getName() << "\t年龄:" << it->getAge()<<endl;
  }
}

运行效果:


a2fbeffc564a42ccaa2d37c9946df330.png


自定义数据类型重载时的要求比较严格:

不仅函数需要加const限制,参数列表中也都要加const

由于Person类中的属性采用了封装,那么在对应的get 方法中也要是常函数

希望以此文章帮助大家快速学会、复习set容器的使用,创作不易,希望大家能够点赞支持!


目录
相关文章
|
1月前
|
存储 搜索推荐 C++
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器2
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器
48 2
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器2
|
1月前
|
存储 C++ 容器
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器1
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器
51 5
|
1月前
|
存储 编译器 C++
【C++篇】揭开 C++ STL list 容器的神秘面纱:从底层设计到高效应用的全景解析(附源码)
【C++篇】揭开 C++ STL list 容器的神秘面纱:从底层设计到高效应用的全景解析(附源码)
53 2
|
3月前
|
安全 编译器 容器
C++STL容器和智能指针
C++STL容器和智能指针
|
2天前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
16 4
|
4天前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
15 4
|
26天前
|
存储 编译器 对象存储
【C++打怪之路Lv5】-- 类和对象(下)
【C++打怪之路Lv5】-- 类和对象(下)
23 4
|
26天前
|
编译器 C语言 C++
【C++打怪之路Lv4】-- 类和对象(中)
【C++打怪之路Lv4】-- 类和对象(中)
20 4
|
26天前
|
存储 安全 C++
【C++打怪之路Lv8】-- string类
【C++打怪之路Lv8】-- string类
18 1
|
1月前
|
存储 编译器 C++
【C++类和对象(下)】——我与C++的不解之缘(五)
【C++类和对象(下)】——我与C++的不解之缘(五)