爱上c++的第十三天:STL标准库

简介: 哈哈哈,今天终于可以更新关于c++知识的最后一个部分的知识了,后面的话我应该就会更新一些关于python和机器学习还有数据结构方面的东西了,毕竟写这个东西也是很花时间的,希望大家多多支持,大家的认可,真的能让我大受鼓舞的,也是一直督促我前进的动力。

你的c++学习路上明灯


哈哈哈,今天终于可以更新关于c++知识的最后一个部分的知识了,后面的话我应该就会更新一些关于python和机器学习还有数据结构方面的东西了,毕竟写这个东西也是很花时间的,希望大家多多支持,大家的认可,真的能让我大受鼓舞的,也是一直督促我前进的动力。


07ee1bb085a24202b43f5ff03b768616.png


一,STL基本概念


1,STL(standard template library)标准模板库


2,STL从广义上分为:容器(container),算法(algorithm),迭代器(iterator)


3,STL几乎所有的代码都采用了模板类或者模板函数


4,容器和算法之间凭借迭代器进行连接


二,STL六大组件


8f7907a40a70453082e34e7df4b4ba93.png


接下来我来分别讲一讲容器,算法,迭代器和仿函数


1,容器:


30665c5ad9084ef5abd4f1e8e75442c1.png


STL容器就是将运用最广泛的一些数据结构凸显出来。

关联式容器概念介绍_遥远的歌s的博客-CSDN博客_关联式容器

https://blog.csdn.net/qq_44819750/article/details/107785732?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164709939216780366580403%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=164709939216780366580403&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-1-107785732.pc_search_result_cache&utm_term=%E5%85%B3%E8%81%94%E5%BC%8F%E5%AE%B9%E5%99%A8&spm=1018.2226.3001.4187


STL之序列式容器(一)、什么是序列式容器_学无止尽,谨言慎行!-CSDN博客

https://blog.csdn.net/y601500359/article/details/105409417?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164709966416780271970753%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=164709966416780271970753&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-1-105409417.pc_search_result_cache&utm_term=%E5%BA%8F%E5%88%97%E5%BC%8F%E5%AE%B9%E5%99%A8&spm=1018.2226.3001.4187


序列式容器这一篇写的是真的不错(那两张图)总结的很好。


2,算法:


有限的步骤,解决逻辑或数学上的问题


说白了,算法就是解决问题的方法


4725c5d12f5e401897fc14bf7cde31e6.png


3,迭代器:


容器和算法之间的粘合剂


实质:提供一种方法,使之能够访问某个容器所含的某些元素,而又无需暴露该容器的内部的表达方式。


每个容器都有自己的专属迭代器。


a556e22f9a704f93b7c344afd72bf7b1.png


4,仿函数


在STL中仿函数就是一种方法,改变一些规则的方法,其实我们学的也不多,简单了解即可。


三,详解STL中的容器


在这里,我会着重讲几个容器,其他的容器就会泛泛而谈,因为他们是相似的。


一,string容器


1,本质:string是c++风格的字符串,而string本质上是一个类。


2,

char*是一个指针。


string是一个类,类内部封装了char*,管理这个字符串,是一个char*的容器


3,特点:


string类内部封装了很多成员方法。(所有STL容器都是),string管理char*所分配的内存,不用担心复制越界和取值越界等问题,由类内部进行负责。


4,构造函数


14ed1a21669046cabab54194861965c7.png


#include<iostream>
#include<string>
using namespace std;
void test1() {
  string s1="hello world";
  const char* str = "hello world";
  string s2(str);
  cout << s2 << endl;
  string s3(s2);
  cout << s3 << endl;
  string s4(8, 'a');
  cout << s4 << endl;
}
int main() {
  test1();
  return 0;
}


5,赋值操作


6ed06e58cfd247528a841a7f928e26bd.png


#include<iostream>
#include<string>
using namespace std;
void test1() {
  string str1;
  str1 = "hello world";
  string str2;
  str2 = str1;
  cout << str2 << endl;
  //string str3='s';
  //str3 = 's';
  string str4;
  str4.assign(str2);
//删除前五个
  string str5;
  str5.assign(str1, 5);
  string str7;
  str7.assign("hello c++", 5);
  string str6;
  str6.assign(10, 'w');
  cout << str5 << endl;
  cout << str7 << endl;
}
int main() {
  test1();
  return 0;
}


6,字符串拼接


775a3dd45ebe4c03916edda787bdc6e8.png


#include<iostream>
using namespace std;
#include<string>
int main() {
  string str1 = "我";
  str1 += "爱玩游戏";
  str1 += ":";
  cout << "str1 = " << str1 << endl;
  string str2 = "LOL CF";
  str1 += str2;
  cout << "str1 = " << str1 << endl;
  string str3 = "I";
  str3.append(" love ");
  str3.append(str2, 3);
  cout << "str3 = " << str3 << endl;
  str3.append(str2);
  cout << "str3 = " << str3 << endl;
  string str4 = "I love game";
  str4.append(str2, 0, 3);
  cout << "str4 = " << str4 << endl;
  return 0;
}


7,字符串查找和替换


ed0fcebeef944e6ebe175169ddf8a581.png


#include<iostream>
#include<string>
using namespace std;
//字符串查找与替换
//1,查找
void test1() {
  string str1 = "abcdefghde";
  int pos = str1.find("df");
  cout << "pos = " << pos << endl;
  if (pos==-1) {
    cout << "未找到" << endl;
  }
  else {
    cout << "已找到,pos = " << pos << endl;
  }
  pos = str1.rfind("de");
  cout << "pos = " << pos << endl;
}
//2.替换
void test2() {
  string str1 = "abcdefghde";
  //虽然只是要替换三个字符,但是后面接的字符串有四个,全部替换上去
  str1.replace(1, 3, "1111");
  cout << "str1 = " << str1 << endl;
}
int main() {
  test1();
  test2();
  return 0;
}


8,字符串比较


cbca120c7d5b4ceb90454460288c4be2.png


9,字符存取


ce2695eaf05b493394d7baaf75f2f4dc.png


#include<iostream>
#include<string>
using namespace std;
void test1() {
  string str1 = "hello";
  //1.利用【】访问
  for (int i = 0; i < str1.size(); i++) {
    cout << str1[i] << " ";
  }
  cout << endl;
  //2,利用at访问
  for (int i = 0; i < str1.size(); i++) {
    cout << str1.at(i) << " ";
  }
  cout << endl;
}
int main() {
  test1();
  return 0;
}


10,string的插入和删除


cb67863524034bf8b0d6ca64010a3788.png


#include<iostream>
#include<string>
using namespace std;
void test1() {
  //1,插入字符串
  string str1 = "hello";
  str1.insert(1, "111");
  cout << "str1 = " << str1 << endl;
  //2,删除
  str1.erase(1, 3);
  cout << "str1 = " << str1 << endl;
}
int main() {
  test1();
  return 0;
}


11,字串获取


4b57aa68ab9c48ce8526d6ce3d848566.png


#include<iostream>
#include<string>
using namespace std;
void test1() {
  string str1 = "hello";
  string subStr = str1.substr(1, 3);
  cout << "subStr = " << subStr << endl;
  //实用操作
  string email = "zhangsan@qq.com";
  int pos = email.find("@");
  cout << "用户名: " << email.substr(0, pos) << endl;
}
int main() {
  test1();
  return 0;
}


string容器是典型的序列式容器,其他的序列式容器的操作大多相同。例如下面要讲的vector容器。


二,vector容器


1,功能:


和数组十分相似,也称为单端数组


2,与普通数组的区别:


数组是静态的,而vector可以动态扩展。


3,什么叫动态扩展?


并不是在原空间之后续接新空间,而是找更大的内存空间,然后将原数据拷贝到新空间,释放原空间。(无法确定后续空间是否已经被使用)


除有与上面所有相同的操作外,还有其他的一些操作


4,vector容器存放数据


1)存放内置数据类型


#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>//标准算法头文件
void MyPrint(int val) {
  cout << val << endl;
}
void test() {
  //创建一个vector数组
  vector<int> v;
  //写入数据
  v.push_back(10);
  v.push_back(20);
  v.push_back(30);
  v.push_back(40);
  //通过迭代器访问容器中的数据
  vector<int>::iterator itBegin = v.begin();
  vector<int>::iterator itEnd = v.end();
  //第一种遍历方式
  while (itBegin != itEnd) {
    cout << *itBegin << endl;
    itBegin++;
  }
  //第二种遍历方式
  for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
    cout << *it << endl;
  }
  //第三种遍历方式
  //利用STL中的遍历算法 
  for_each(v.begin(), v.end(), MyPrint);
}
int main() {
  test();
  return 0;
}


2)存放自定义数据类型


#include<iostream>
#include<vector>
#include<string>
using namespace std;
class person {
public:
  string m_Name;
  int m_Age;
  person(string name, int age) {
    this->m_Age = age;
    this->m_Name = name;
  }
};
//存放对象
void test1() {
  vector<person> v;
  person p1("a", 1);
  person p2("a", 2);
  person p3("a", 3);
  person p4("a", 4);
  person p5("a", 5);
  v.push_back(p1);
  v.push_back(p2);
  v.push_back(p3);
  v.push_back(p4);
  v.push_back(p5);
  for (vector<person>::iterator it = v.begin(); it < v.end(); it++) {
    cout << "年龄:" << (*it).m_Age << " 姓名:" << (*it).m_Name << endl;
    cout << "年龄:" << it->m_Age << " 姓名:" << it->m_Name << endl;
  }
}
//存放指针
void test2() {
  vector<person*> v2;
  person p1("a", 1);
  person p2("a", 2);
  person p3("a", 3);
  person p4("a", 4);
  person p5("a", 5);
  v2.push_back(&p1);
  v2.push_back(&p2);
  v2.push_back(&p3);
  v2.push_back(&p4);
  v2.push_back(&p5);
  for (vector<person*>::iterator it = v2.begin(); it < v2.end(); it++) {
    cout << "年龄:" << (*it)->m_Age << " 姓名:" << (*it)->m_Name << endl;
  }
}
int main() {
  test1();
  test2();
  return 0;
}


5,vector容器的迭代器是支持随机访问的迭代器。


6,vector互换容器


f47a6098b01f486aa2de2f9392a56d84.png


#include<iostream>
#include<vector>
using namespace std;
void PrintVector(vector<int>& v) {
  for (vector<int>::iterator it = v.begin(); it < v.end(); it++) {
    cout << *it << " ";
  }
  cout << endl;
}
void test1() {
  cout << "互换前:" << endl;
  vector<int> v1;
  for (int i = 0; i < 10; i++) {
    v1.push_back(i);
  }
  PrintVector(v1);
  vector<int> v2;
  for (int i = 9; i >= 0; i--) {
    v2.push_back(i);
  }
  PrintVector(v2);
  //互换容器
  cout << "互换后:" << endl;
  v1.swap(v2);
  PrintVector(v1);
  PrintVector(v2);
}
//实用操作,收缩内存
void test2() {
  vector<int> v;
  for (int i = 0; i < 10000; i++) {
    v.push_back(i);
  }
  cout << "v的容量为:" << v.capacity() << endl;
  cout << "v的大小为:" << v.size() << endl;
  //只是重新指定大小,容量不变
  v.resize(3);
  cout << "v的容量为:" << v.capacity() << endl;
  cout << "v的大小为:" << v.size() << endl;
  //收缩内存
  //当前行结束后,匿名对象的空间就会被释放
  vector<int>(v).swap(v);//匿名对象
  cout << "v的容量为:" << v.capacity() << endl;
  cout << "v的大小为:" << v.size() << endl;
}
int main() {
  test1();
  test2();
  return 0;
}


7,预留空间


76db908b6ef14845b8e3bfdf5901acb8.png


#include<iostream>
#include<vector>
using namespace std;
void test1() {
  //reserve预留空间,预留位置不初始化,元素不可访问
  vector<int> v1;
  int num = 0;
  int* p = NULL;
  v1.reserve(10000);
  for (int i = 0; i < 10000; i++) {
    v1.push_back(i);
    if (p != &v1[0]) {
      p = &v1[0];
      num++;
    }
  }
  cout << "num = " << num << endl;
}
int main() {
  test1();
  return 0;
}


8,一个小知识点


vector的容量大于等于vector的大小。


9,resize用法

c++ vector resize & reserve_jackywgw的博客-CSDN博客

https://blog.csdn.net/jackywgw/article/details/6248342


三,deque容器


1,功能:


双端数组,可以对头端进行插入删除操作


2,deque与vector的区别:


1)vector对于头部的插入效率低,数据量越大,效率越低。


2)deque容器对头部的插入速度更快


3)vector容器访问元素时会更快,这和两者内部实现有关


3,deque内部工作原理:


deque内部有个中控器,维护每段缓冲区中的内容,缓冲区内存放数据


中控器维护的是每个缓冲区的地址,使得使用deque容器时像一片连续的空间。


7b81d8136db447b0b60212fadc9d03a0.png


4,deque容器的迭代器也是支持随机访问的


5,对于支持随机访问迭代器的容器,都可以利用sort算法排序。


6,deque排序


357e4d5adc8d49bea2dcae6cc9821121.png


#include<iostream>
#include<deque>
using namespace std;
#include<algorithm>
void PrintDeque(const deque<int>d) {
  for (deque<int>::const_iterator it = d.begin(); it < d.end(); it++) {
    cout << *it << " ";
  }
  cout << endl;
}
void test1() {
  deque<int>d;
  d.push_back(10);
  d.push_back(50);
  d.push_back(9000);
  d.push_back(570);
  d.push_back(1);
  //排序算法,默认为升序
    //对于支持随机访问迭代器的容器,都可以利用sort算法直接对其排序
  sort(d.begin(), d.end());
  PrintDeque(d);
}
int main() {
  test1();
  return 0;
}


7,deque构造函数


6313af190096430493a6b6a842b3f647.png


#include<iostream>
using namespace std;
#include<deque>
void PrintDeque(const deque<int>d) {
  for (deque<int>::const_iterator it = d.begin(); it < d.end(); it++)
  {
    cout << *it << " ";
  }
  cout << endl;
}
void test1() {
  deque<int>d1;
  for (int i = 0; i < 10; i++) {
    d1.push_back(i);
  }
  PrintDeque(d1);
  deque<int>d2(d1.begin(), d1.end());
  PrintDeque(d2);
  deque<int>d3(10, 1000);
  PrintDeque(d3);
  deque<int>d4(d3);
  PrintDeque(d4);
}
int main() {
  test1();
  return 0;
}


四,案例


#include<iostream>
#include<deque>
#include<vector>
using namespace std;
#include<string>
#include<algorithm>
#include<ctime>
//评委打分
class person {
public:
  int m_Score;//分数
  string m_Name;//姓名
  person(string name, int score) {
    this->m_Name = name;
    this->m_Score = score;
  }
};
void CreatePerson(vector<person>&v) {
  string nameseed = "ABCDE";
  for (int i = 0; i < 5; i++) {
    string name = "选手";
    name += nameseed[i];
    int score = 0;
    person p(name, score);
    v.push_back(p);
  }
}
void SetScore(vector<person>&v) {
  for (vector<person>::iterator it = v.begin(); it != v.end(); it++) {
    //存放评委打的分数
    deque<int>d;
    for (int i = 0; i < 10; i++) {
      int score = rand() % 41 + 60;//60~100分
      d.push_back(score);
    }
    //排序
    sort(d.begin(), d.end());
    //去除最高和最低分
    d.pop_back();
    d.pop_front();
    int sum = 0;
    for (deque<int>::iterator dit = d.begin(); dit != d.end(); dit++) {
      sum += *dit;
    }
    int ave = sum / d.size();
    it->m_Score = ave;
  }
}
void showScore(vector<person>&v) {
  for (vector<person>::iterator it = v.begin(); it != v.end(); it++) {
    cout << "姓名:" << it->m_Name << " 平均分:" << it->m_Score << endl;
  }
}
int main() {
  //创造随机数种子
  srand((unsigned int)time(NULL));
  //1,创造5名选手
  vector<person>v;//存放选手的容器
  CreatePerson(v);
  //2,给选手打分
  SetScore(v);
  //3.显示最后得分
  showScore(v);
  return 0;
}


五,stack容器(栈容器)


概念:一种先进后出的数据结构,它只有一个出口,栈中只有顶端的元素才能够被外界使用。


(因此栈不允许有遍历行为)


六,queue容器(队列容器)


概念:一种先进先出的数据结构,有两个出口;


队尾进数据,队头出数据。


队列中只有队头和队尾能被外界使用,因此队列不能被遍历


七,list容器(双向循环链表)


e9370cf66712445d905235ba2df63a91.png


1,由于链表的存储方式并不是连续的内存空间,因此链表list只支持前移和后移,属于双向迭代器。


2,list的优点:


1)采用动态内存分配,不会造成内存的浪费和溢出


2)链表执行插入和删除操作十分方便,修改指针即可


3,缺点:


链表灵活,但是空间(指针域)和时间(遍历)额外耗费较大


4.list有一个重要的性质,插入和删除操作都不会造成原有list迭代器的失效,这在vector中是不成立的。


5,反转和排序


dbe1666fd14d4d39bb86434ca0b22714.png


6.list容器-排序案例


#include<iostream>
using namespace std;
#include<list>
//排序案例
//将person自定义数据类型进行排序,
//排序规则:按照年龄进行升序,如果年龄相同按照升高进行降序
class person {
public:
  person(string name, int age, int height) {
    this->m_Age = age;
    this->m_Height = height;
    this->m_Name = name;
  }
  string m_Name;
  int m_Age;
  int m_Height;
};
int ComparePerson(person& p1, person& p2) {
  if (p1.m_Age == p2.m_Age) {
    return p1.m_Height > p2.m_Height;
  }
  return p1.m_Age < p2.m_Age;
}
void test1() {
  list<person>L;
  person p1("唐僧", 28, 180);
  person p2("孙悟空", 567, 159);
  person p3("猪八戒", 567, 179);
  person p4("沙僧", 567, 167);
  L.push_back(p1);
  L.push_back(p2);
  L.push_back(p3);
  L.push_back(p4);
  for (list<person>::const_iterator it = L.begin(); it != L.end();it++) {
    cout << " 姓名: " << it->m_Name << " " 
      << " 年龄: " << it->m_Age << " " << " 身高: " << it->m_Height << endl;
  }
  cout << "------------------------------" << endl;
  L.sort(ComparePerson);
  for (list<person>::const_iterator it = L.begin(); it != L.end(); it++) {
    cout << "姓名: " << it->m_Name << " "
      << "年龄: " << it->m_Age << " " << "身高: " << it->m_Height << endl;
  }
}
int main() {
  test1();
  return 0;
}


***不支持随机访问迭代器的容器,内部都会提供一些对应的算法


八,set/multiset容器(关联式容器)


所有元素都会在插入时自动排序,


1,本质:


底层结构是二叉树


2,二者的区别:


1)set中不允许有重复元素


2)multiset中允许有重复元素


3)set插入数据的同时会返回插入结果,表示插入是否成功。


4)multiset不会检测数据,因此可以重复插入


#include<iostream>
using namespace std;
#include<set>
void test1() {
  set<int>s1;
  pair<set<int>::iterator, bool> it = s1.insert(10);
  if (it.second) {
    cout << "第一次插入成功" << endl;
  }
  else {
    cout << "第一次插入失败" << endl;
  }
  it = s1.insert(10);
  if (it.second) {
    cout << "第二次插入成功" << endl;
  }
  else {
    cout << "第二次插入失败" << endl;
  }
}
int main() {
  test1();
  return 0;
}


3,构造与赋值


插入数据只能用insert函数


#include<iostream>
#include<set>
using namespace std;
void PrintSet(set<int>&s) {
  for (set<int>::iterator it = s.begin(); it != s.end(); it++) {
    cout << *it << " ";
  }
  cout << endl;
}
void test1() {
  set<int>s1;
  //只能用insert方式
  s1.insert(10);
  s1.insert(10);
  s1.insert(50);
  s1.insert(40);
  s1.insert(49);
  //set容器的特点,所有元素插入时候自动被排序
  //set容器不允许插入重复值
  PrintSet(s1);
}
int main() {
  test1();
  return 0;
}


4,查找与统计


#include<iostream>
#include<set>
using namespace std;
//查找
void test1() {
  set<int>s;
  s.insert(10);
  s.insert(30);
  s.insert(40);
  s.insert(60);
  s.insert(50);
  set<int>::iterator pos = s.find(30);
  if (pos != s.end()) {
    cout << "找到元素。" << endl;
  }
  else {
    cout << "未找到元素。" << endl;
  }
}
//统计元素个数
void test2() {
  set<int>s;
  s.insert(10);
  s.insert(30);
  s.insert(40);
  s.insert(60);
  s.insert(50);
  //查找元素的个数
  int num = s.count(30);
  cout << "num = " << num << endl;
}
int main() {
  test1();
  test2();
  return 0;
}


5,排序规则


利用仿函数可以改变set容器中的排序规则

1)内置数据类型

2)自定义数据类型


#include<iostream>
#include<set>
using namespace std;
class MyCompare {
public:
  bool operator()(int a,int b) {
    return a > b;
  }
};
void test1() {
  set<int>s1;
  s1.insert(10);
  s1.insert(40);
  s1.insert(20);
  s1.insert(30);
  for (set<int>::iterator it = s1.begin(); it != s1.end(); it++) {
    cout << *it << " ";
  }
  cout << endl;
  set<int, MyCompare>s2;
  s2.insert(10);
  s2.insert(40);
  s2.insert(20);
  s2.insert(30);
  for (set<int, MyCompare>::iterator it = s2.begin(); it != s2.end(); it++) {
    cout << *it << " ";
  }
  cout << endl;
}
int main() {
  test1();
  return 0;
}


九,pair对组的创建


931714700f7341208e1b7cb073758287.png


#include<iostream>
#include<string>
using namespace std;
void test1() {
  //第一种方式
  pair<string, int>p1("Tom", 20);
  cout << "姓名: " << p1.first << "年龄:" << p1.second << endl;
  //第二种方式
  pair<string, int>p2("Jerry", 18);
  cout << "姓名: " << p2.first << "年龄:" << p2.second << endl;
}
int main() {
  test1();
}


十,map/multimap容器(效率高)


map<T,T>p;


1,简介:


1)map中所有元素都是pair


2)pair中的第一个元素为key(键值),起到索引作用,第二个元素为value(实值)


3)所有元素都会根据元素的键值自动排序


2,本质:


该容器属于关联式容器,底层结构是二叉树实现


3,优点:


可以根据key值快速找到vlaue(高效的原因)


4,map不允许重复值


multimap允许重复值


十一,注意


1)所有容器的迭代器都可进行的操作


*iter 、 ++iter 、 --iter、 iter1==iter2、 iter1!=iter2


2)vector和deque容器的迭代器可进行的额外操作


iter+n、 iter-n 、 > 、 >= 、 < 、 <=


注:这是因为vector和deque容器实际上是两个数组,只有对数组才能执行额外操作;


十二,容器嵌套容器


#include<iostream>
#include<vector>
#include<string>
using namespace std;
class person {
public:
  string m_Name;
  int m_Age;
  person(string name, int age) {
    this->m_Age = age;
    this->m_Name = name;
  }
};
//存放对象
void test1() {
  vector<person> v;
  person p1("a", 1);
  person p2("a", 2);
  person p3("a", 3);
  person p4("a", 4);
  person p5("a", 5);
  v.push_back(p1);
  v.push_back(p2);
  v.push_back(p3);
  v.push_back(p4);
  v.push_back(p5);
  for (vector<person>::iterator it = v.begin(); it < v.end(); it++) {
    cout << "年龄:" << (*it).m_Age << " 姓名:" << (*it).m_Name << endl;
    cout << "年龄:" << it->m_Age << " 姓名:" << it->m_Name << endl;
  }
}
//存放指针
void test2() {
  vector<person*> v2;
  person p1("a", 1);
  person p2("a", 2);
  person p3("a", 3);
  person p4("a", 4);
  person p5("a", 5);
  v2.push_back(&p1);
  v2.push_back(&p2);
  v2.push_back(&p3);
  v2.push_back(&p4);
  v2.push_back(&p5);
  for (vector<person*>::iterator it = v2.begin(); it < v2.end(); it++) {
    cout << "年龄:" << (*it)->m_Age << " 姓名:" << (*it)->m_Name << endl;
  }
}
int main() {
  test1();
  test2();
  return 0;
}


十三,总结


1,对于自定义数据类型,必须要指定排序规则,否则编译器不知道如何排序。


2,高级排序只是在排序规则上再进行一次逻辑规则制定即可,不是很复杂。

目录
相关文章
|
1天前
|
XML 网络协议 API
超级好用的C++实用库之服务包装类
通过本文对Boost.Asio、gRPC和Poco三个超级好用的C++服务包装类库的详细介绍,开发者可以根据自己的需求选择合适的库来简化开发工作,提高代码的效率和可维护性。每个库都有其独特的优势和适用场景,合理使用这些库可以极大地提升C++开发的生产力。
24 11
|
7天前
|
编译器 C语言 C++
【c++丨STL】list模拟实现(附源码)
本文介绍了如何模拟实现C++中的`list`容器。`list`底层采用双向带头循环链表结构,相较于`vector`和`string`更为复杂。文章首先回顾了`list`的基本结构和常用接口,然后详细讲解了节点、迭代器及容器的实现过程。 最终,通过这些步骤,我们成功模拟实现了`list`容器的功能。文章最后提供了完整的代码实现,并简要总结了实现过程中的关键点。 如果你对双向链表或`list`的底层实现感兴趣,建议先掌握相关基础知识后再阅读本文,以便更好地理解内容。
15 1
|
19天前
|
算法 C语言 C++
【c++丨STL】list的使用
本文介绍了STL容器`list`的使用方法及其主要功能。`list`是一种双向链表结构,适用于频繁的插入和删除操作。文章详细讲解了`list`的构造函数、析构函数、赋值重载、迭代器、容量接口、元素访问接口、增删查改操作以及一些特有的操作接口如`splice`、`remove_if`、`unique`、`merge`、`sort`和`reverse`。通过示例代码,读者可以更好地理解如何使用这些接口。最后,作者总结了`list`的特点和适用场景,并预告了后续关于`list`模拟实现的文章。
33 7
|
2月前
|
存储 编译器 C语言
【c++丨STL】vector的使用
本文介绍了C++ STL中的`vector`容器,包括其基本概念、主要接口及其使用方法。`vector`是一种动态数组,能够根据需要自动调整大小,提供了丰富的操作接口,如增删查改等。文章详细解释了`vector`的构造函数、赋值运算符、容量接口、迭代器接口、元素访问接口以及一些常用的增删操作函数。最后,还展示了如何使用`vector`创建字符串数组,体现了`vector`在实际编程中的灵活性和实用性。
66 4
|
2月前
|
C语言 C++ 容器
【c++丨STL】string模拟实现(附源码)
本文详细介绍了如何模拟实现C++ STL中的`string`类,包括其构造函数、拷贝构造、赋值重载、析构函数等基本功能,以及字符串的插入、删除、查找、比较等操作。文章还展示了如何实现输入输出流操作符,使自定义的`string`类能够方便地与`cin`和`cout`配合使用。通过这些实现,读者不仅能加深对`string`类的理解,还能提升对C++编程技巧的掌握。
81 5
|
2月前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
63 2
|
2月前
|
存储 算法 Linux
【c++】STL简介
本文介绍了C++标准模板库(STL)的基本概念、组成部分及学习方法,强调了STL在提高编程效率和代码复用性方面的重要性。文章详细解析了STL的六大组件:容器、算法、迭代器、仿函数、配接器和空间配置器,并提出了学习STL的三个层次,旨在帮助读者深入理解和掌握STL。
61 0
|
22天前
|
存储 编译器 C语言
【c++丨STL】vector模拟实现
本文深入探讨了 `vector` 的底层实现原理,并尝试模拟实现其结构及常用接口。首先介绍了 `vector` 的底层是动态顺序表,使用三个迭代器(指针)来维护数组,分别为 `start`、`finish` 和 `end_of_storage`。接着详细讲解了如何实现 `vector` 的各种构造函数、析构函数、容量接口、迭代器接口、插入和删除操作等。最后提供了完整的模拟实现代码,帮助读者更好地理解和掌握 `vector` 的实现细节。
30 0
|
2月前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
113 5
|
2月前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
112 4