C++——8(智能指针&STL)
一、智能指针
头文件:
智能指针:智能指针(smart pointer)是个特殊的类模板,重载了->和*运算符,实现了C++的自动内存回收机制。
分类:
auto_ptr:C++11中已经弃用,有设计缺陷不足之处
shared_ptr:共享智能指针,允许多个智能指针共享同一资源,通过引用计数自动管理内存。(当引用该指针的数目为0时,自动释放)
- 核心原理:
每个
shared_ptr维护一个 “引用计数”,记录有多少个shared_ptr指向同一资源。当新的
shared_ptr指向资源时,计数 + 1;当shared_ptr销毁或重新赋值时,计数 - 1。当计数为
0时,自动释放资源。/*=============================================== * 文件名称:2_SharedPoint.cpp * 创 建 者:青木莲华 * 创建日期:2025年09月04日 * 描 述:智能指针_Shared 示例 ================================================*/ #include <iostream> using namespace std; #include <memory> #include <unistd.h> class Demo { public: Demo(){ cout << __func__ << endl; } ~Demo(){ cout << __func__ << endl; } void func() { cout << "Demo::func()" << endl; } }; void test() { //定义共享智能指针 不安全写法 //shared_ptr<Demo> p(new Demo()); //安全写法 安全创建堆区空间 shared_ptr<Demo> p = make_shared<Demo>(); //计数值 = 1 shared_ptr<Demo> p2 = p; //计数值 = 2 p->func(); p.reset(); //结束生命周期(智能指针),引用计数值 = 1 sleep(3); //sleep延时,查看是否释放资源 p2->func(); //执行完后,函数结束,引用计数值 == 0 ,自动回收资源 } int main(int argc, char *argv[]) { test(); return 0; }
运行截图
unique_ptr:独占资源智能指针,资源只能被一个unique_ptr持有(独占所有权),转移所有权后原指针失效。
- 核心特点:
不可拷贝,只能移动:通过
std::move转移所有权,原指针变为nullptr。高效轻量:无引用计数开销,性能接近原始指针。
支持自定义删除器:可管理非内存资源(如文件句柄、网络连接)。
兼容 STL 容器:因支持移动语义,可安全存入
vector等容器。#include <iostream> using namespace std; #include <memory> class Demo { public: Demo(){ cout << __func__ << endl; } ~Demo(){ cout << __func__ << endl; } void func() { cout << "Demo::func()" << endl; } }; unique_ptr<Demo> test() { //资源独占智能指针 unique_ptr<Demo> p = make_unique<Demo>(); p->func(); //unique_ptr<Demo> p2(p); 不能直接初始化,因为独占 //移交所有权 p ---> p2 , p = nullptr; unique_ptr<Demo> p2 = move(p); p2->func(); //return p2; (隐式)函数返回unique指针时,会自动移交所有权 return move(p2); //显示返回移交 } int main(int argc, char *argv[]) { unique_ptr<Demo> p = test(); //接收返回指针,并接收所有权 cout << "-----------" << endl; p->func(); return 0; }
运行结果
weak_ptr:配合shared_ptr使用,不增加引用计数,用于解决shared_ptr的循环引用问题。
- 核心特点:
不管理资源生命周期,仅 “观察”
shared_ptr管理的资源。通过
lock()方法获取shared_ptr(若资源未释放),或用expired()检查资源是否有效。/*=============================================== * 文件名称:4_WeakPoint.cpp * 创 建 者:青木莲华 * 创建日期:2025年09月04日 * 描 述:智能指针_Weak 示例 ================================================*/ #include <iostream> using namespace std; #include <memory> #include <unistd.h> class Demo { public: Demo(){ cout << __func__ << endl; } ~Demo(){ cout << __func__ << endl; } void func() { cout << "Demo::func()" << endl; } }; void test() { shared_ptr<Demo> p = make_shared<Demo>(); weak_ptr<Demo> wp = p; //协助管理shared_ptr p->func(); if(wp.expired()) //判断堆区中对象是否释放 { cout << "Obj is not exist" << endl; } else { cout << "Obj exist" << endl; } p.reset(); //结束shared_ptr生命周期 if(wp.expired()) //判断堆区中对象是否释放 { cout << "Obj is not exist" << endl; } else { cout << "Obj exist" << endl; } } int main(int argc, char *argv[]) { test(); return 0; }
运行结果
智能指针 所有权 线程安全 适用场景 核心缺陷 auto_ptr独占(旧版) 否 简单场景(已弃用) 所有权转移易出错、功能弱 shared_ptr共享 引用计数线程安全 多指针共享资源 循环引用导致内存泄漏 unique_ptr独占 否 单指针管理资源、STL 容器 不可共享 weak_ptr弱引用(无) 否 解决 shared_ptr 循环引用 不能直接访问资源
二、标准模板库 (STL)
STL:主要是一些容器的集合,list、vector、set、map等。
目的:标准化组件,可以使用现成的组件。
分类:
容器:实现了数组、链表、队列、等等,实质是模板类迭代器:一种复杂的指针,可以通过其读写容器中的对象,实质是运算符重载- 空间配置器:容器的空间配置管理的模板类
- 配接器:用来修饰容器、仿函数、迭代器接口
算法:算法通过迭代器对容器实现相关操作- 仿函数:类似函数,通过重载()运算符来模拟函数行为的类
组件间关系:
container(容器)通过allocator(配置器)取得数据储存空间,algorithm(算法)通过iterator(迭代器)存取container(容器)内容,functor(仿函数)可以协助algorithm(算法)完成不同的策略变化,adapter(配接器)可以修饰或套接functor(仿函数)。
三、容器(Container)
序列容器
Vector:动态数组容器
Deque:双端队列容器
list:双向链表容器关联容器
Set / multiset:根据元素值自动排序,由红黑树实现,便于查找(set内相同元素只能出现一次,multiset可以存在多次)map / multimap:成对的键值 / 实值,由红黑树实现(map 内相同元素只能出现一次,multimap可以出现多次)Hash相关:hash_map、hash_set、hash_multimap、hash_multiset等
1.List 集合
概述:
<list>是一个非常重要的容器类,用于存储元素集合,支持双向迭代器。<list>是 C++ 标准模板库(STL)中的一个序列容器,它允许在容器的任意位置快速插入和删除元素。不需要在创建时指定大小,并且可以在任何位置添加或删除元素,而不需要重新分配内存。以下是
<list>容器的一些基本操作:
- 包含头文件:
#include <list>- 声明列表:
std::list<T> mylist;,其中T是存储在列表中的元素类型。- 插入元素:
mylist.push_back(value);- 删除元素:
mylist.pop_back();或mylist.erase(iterator);- 访问元素:
mylist.front();和mylist.back();- 遍历列表:使用迭代器
for (auto it = mylist.begin(); it != mylist.end(); ++it)特点
- 双向迭代:
<list>提供了双向迭代器,可以向前和向后遍历元素。- 动态大小:与数组不同,
<list>的大小可以动态变化,不需要预先分配固定大小的内存。- 快速插入和删除:可以在列表的任何位置快速插入或删除元素,而不需要像向量那样移动大量元素。
示例代码:/*=============================================== * 文件名称:List.cpp * 创 建 者:青木莲华 * 创建日期:2025年09月04日 * 描 述:集合示例 ================================================*/ #include <iostream> using namespace std; #include <list> class Good { public: Good(){} Good(string name , string note , double price): g_name(name) , g_note(note) , g_price(price) {} friend ostream& operator<<(ostream& out,const Good &g) { out << "商品名:" << g.g_name << endl; out << "商品简介:" << g.g_note << endl; out << "商品价格:" << g.g_price << endl; return out; } private: string g_name; string g_note; double g_price; }; int main(int argc, char *argv[]) { Good good_a("小牛","牛牛的小牛车",20000); Good good_b("大牛","牛牛的大牛兰博基尼",9999999); Good good_c("二牛","牛牛的二手车",1000); list<Good> goods; goods.push_back(good_a); goods.push_back(good_b); goods.push_back(good_c); for(Good good : goods) { cout << good << endl; cout << "=======================" << endl; } return 0; }
运行截图
2.Vector 动态数组
概述:C++ 中的 vector 是一种序列容器,它允许你在运行时动态地插入和删除元素。vector 是基于数组的数据结构,但它可以自动管理内存,这意味着你不需要手动分配和释放内存。- 基本特性:
- 动态大小:
vector的大小可以根据需要自动增长和缩小。- 连续存储:
vector中的元素在内存中是连续存储的,这使得访问元素非常快速。- 可迭代:
vector可以被迭代,你可以使用循环(如for循环)来访问它的元素。- 元素类型:
vector可以存储任何类型的元素,包括内置类型、对象、指针等。
vector示例:/*=============================================== * 文件名称:Vector.cpp * 创 建 者:青木莲华 * 创建日期:2025年09月04日 * 描 述:Vector容器 ================================================*/ #include <iostream> using namespace std; #include <vector> class Student { public: //无参 Student(){} //有参 Student(string sno,string sname,int age,bool gender) :sno(sno),sname(sname),sage(age),gender(gender){}; //重构输出 friend ostream& operator<<(ostream &out,const Student *stu) { out << "学号:" << stu->sno << endl; out << "姓名:" << stu->sname << endl; out << "年龄:" << stu->sage << endl; string gen = (stu->gender ? "男" : "女"); out << "性别:" << gen << endl; return out; } private: string sno; string sname; int sage; bool gender; }; int main(int argc, char *argv[]) { //1.创建Student Vector 默认为空 vector<Student *> students; //2.添加元素 尾部插入 students.push_back(new Student("25060101", "张三",18,true)); students.push_back(new Student("25060102", "李四",20,true)); students.push_back(new Student("25060103", "王五",19,false)); //打印vector元素个数 cout << "vector_size = " << students.size() << endl; cout << "=====================" << endl; //迭代打印 + 回收资源 for(Student *stu : students) { cout << stu << endl; delete stu; } students.clear(); cout << "=====================" << endl; cout << "vector_size = " << students.size() << endl; return 0; }
运行截图
3.Deque 双端队列
概述:在 C++中,
<deque>是标准模板库(STL)的一部分,它提供了双端队列(double-ended queue)的实现。双端队列是一种允许在两端进行插入和删除操作的线性数据结构。
常用操作:
函数名称 功能描述 deque()默认构造函数,创建一个空的 deque容器。deque(size_type n)创建一个包含 n个默认值元素的deque容器。push_back(const T& value)在容器末尾添加 value元素。pop_back()移除容器末尾的元素。 push_front(const T& value)在容器前端添加 value元素。pop_front()移除容器前端的元素。 insert(iterator pos, const T& value)在 pos位置插入value元素。erase(iterator pos)移除 pos位置的元素。size()返回容器中的元素个数。 clear()清除容器中的所有元素。 at(size_type pos)返回 pos位置的元素,并进行范围检查。front()返回第一个元素的引用。 back()返回最后一个元素的引用。 begin()返回指向第一个元素的迭代器。 end()返回指向末尾元素后一位置的迭代器。
dequeue示例:/*=============================================== * 文件名称:Deque.cpp * 创 建 者:青木莲华 * 创建日期:2025年09月04日 * 描 述:双端队列示例 ================================================*/ #include <iostream> using namespace std; #include <deque> class Good { public: Good(){} Good(string name , string note , double price): g_name(name) , g_note(note) , g_price(price) {} friend ostream& operator<<(ostream& out,const Good &g) { out << "商品名:" << g.g_name << endl; out << "商品简介:" << g.g_note << endl; out << "商品价格:" << g.g_price << endl; return out; } private: string g_name; string g_note; double g_price; }; int main(int argc, char *argv[]) { deque<Good> goods; Good good_a("小牛","牛牛的小牛车",20000); Good good_b("大牛","牛牛的大牛兰博基尼",9999999); Good good_c("二牛","牛牛的二手车",1000); goods.push_back(good_a); goods.push_back(good_b); goods.push_back(good_c); for(Good good : goods) { cout << good << endl; cout << "=======================" << endl; } return 0; }
运行截图

京公网安备 11010502036488号