十三、指针和引用(三)
1、std::unique_ptr(唯一智能指针)
1)概念
std::unique_ptr是所谓的智能指针的一种,主要目的是为了解决原生指针安全性不足的弊端
//std::unique_ptr指针的声明语法std::unqiue_ptr变量名称{};//示例std::unique_ptrptrA{std::make_unique(150)}; // 申请一个具有1个int类型大小的指针,值为150std::cout<<*ptrA; //指针使用std::unique_ptrptrB{new int[5]}; //C++14之前的写法,申请一个具有5个int类型大小的指针std::unique_ptrptrB{std::make_unique(10)}; //申请一个具有5个int类型大小的指针ptrB[0]=250; //指针使用,此声明方法,只能通过数组访问
2)唯一智能指针特性
std::unique_ptr的特点是该指针具有唯一性,因此无法让两个std::unique_ptr指针存放相同的内存地址,如下:
std::unique_ptrptrA{std::make_unique(150)};std::unique_ptrptrB{};//ptrA=ptrB; //错误,无法直接赋值
#include int main(){int* a = new int[5];std::unique_ptrintptr{ std::make_unique(5) }; //申请一个具有5个int类型大小的指针std::unique_ptrintptrA{ std::make_unique(5) }; // 申请一个具有1个int类型大小的指针,值为5std::cout << intptr << " " << intptr[0]<<std::endl; //013D5C98 0std::cout << intptrA << " " << *intptrA << std::endl; //013DEC10 5}
3)reset()用法
reset将会释放std::unique_ptr的内存空间,并且将std::unique_ptr设置为nullptr;
//reset()用法示例std::unique_ptrptrA{std::make_unique(150)};ptrA.reset(); //此时ptrA的内存空间被释放,ptrA的值设置成了nullptr
//reset()示例#include int main(){int* a = new int[5];delete[] a; //释放new申请的内存空间std::unique_ptrptrA{ std::make_unique(100) };std::cout << "释放内存前的地址:"<<ptrA << std::endl;ptrA.reset(); //释放唯一智能指针std::cout << "释放内存后的地址:" << ptrA << std::endl;}
4)get()用法:返回一个std::unique_ptr的指针
//get()用法std::unique_ptrptrA{std::make_unique(150)};int*p = ptrA.get(); //相当于将ptrA申请时的内存赋值给p
5)release()用法
relsease将会返回std::unique_ptr的指针,并且将std::unique_ptr设置为nullptr,但是注意release并不会释放其占用的内存空间
//relseae()用法std::unique_ptrptrA{std::make_unique(150)};int* p = ptrA.release(); //此时ptrA占用的内存空间没有被释放,ptrA的值设置成了nullptr,p等于ptrA申请内存时的地址
//release只是将申请的内存地址设置为了0,并没有释放,并且将原理的地址进行了返回#include int main(){int* a = new int[5];std::unique_ptrptrA{ std::make_unique(100) };std::cout << "release前的地址:" << ptrA << std::endl;a = ptrA.release();std::cout << "release后的地址:" << ptrA << std::endl;std::cout << "a的地址:" << a << std::endl;}
6)唯一智能指针的转移(move)
std::unique_ptr指针因为具有唯一性,因此不能被复制,但是可以转移
//唯一智能指针转移语法转移后的指针变量=std::move(转移前的指针变量);//示例std::unique_ptrptrA{std::make_unique(150)};std::unique_ptrptrB;ptrB=std::move(ptrA); //将ptrA的地址转移到ptrB,转移后ptrA被设置为nullptr
2、std::shared_per(共享智能指针)
1)共享智能指针语法
//共享智能指针语法std::shared_ptr变量名称{};//示例std::shared_ptrptrA{};std::shared_ptrptrB{std::make_shared(5)};//注:std::make_shared不支持新式的数组的定义方式,只能通过new的方式std::shared_ptrptr{new int[5]{1,2,3,4,5}};
//共享智能指针的定义及使用#include int main(){int* a{};std::shared_ptrptrA{ std::make_shared(5) };std::shared_ptrptrB{ ptrA }; //共享ptrA的内存地址std::shared_ptrptrC{ ptrA };std::cout << "ptrA的内存地址为:" << ptrA << std::endl;std::cout << "ptrB的内存地址为:" << ptrB << std::endl;std::cout << "ptrA的内存地址为:" << ptrC << std::endl;std::cout << "\n";std::cout << "ptrA的值为:" << *ptrA << std::endl;std::cout << "ptrB的值为:" << *ptrB << std::endl;}
2)共享智能指针特性
可以有多个std::shared_ptr指向同一地址,同一地址下只有当最后一个std::shared_ptr释放的时候,才会释放其占用的内存空间,std::shared_ptr会记录当前地址有多少个智能指针调用
3)统计共享指针当前有多少个对象调用(use_count)
//统计共享指针当前有多少个对象调用long std::shared_ptr.use_count(); .user_count(); //会返回当前指针共有多少个对象调用
//use.count()用法示例#include int main(){int* a{};std::shared_ptrptrA{ std::make_shared(5) };std::shared_ptrptrB{ ptrA }; //共享ptrA的内存地址std::shared_ptrptrC{ ptrA };std::cout << "ptrA指针共有多少个指针调用:" << ptrA.use_count() << std::endl;}
5)判断共享智能指针是否唯一(unique)
//判断共享智能指针是否唯一bool std::shared_ptr.unique();//unique()返回一个bool值,如果当前智能指针是唯一拥有该指针的,那么返回true,负责返回false注:C++17标准无法使用该函数,只能在17之前使用
//unique()用法#include int main(){int* a{};std::shared_ptrptrA{ std::make_shared(5) };std::cout << "判断指针指针ptrA是否唯一:" << ptrA.unique() << std::endl;std::shared_ptrptrB{ ptrA }; //共享ptrA的内存地址std::shared_ptrptrC{ ptrA };std::cout << "判断指针指针ptrA是否唯一:" << ptrA.unique() << std::endl;}
4)共享智能指针的释放
reset()会将当前共享指针设置为nullptr,同时如果当前智能指针是最后一个拥有该指针的对象,那么将会释放内存。只有最后一个指针变量释放,才能释放内存空间
//共享智能指针的释放std::shared_ptr.reset();
//reset()使用#include int main(){int* a{};std::shared_ptrptrA{ std::make_shared(5) };std::shared_ptrptrB{ ptrA }; //共享ptrA的内存地址std::shared_ptrptrC{ ptrA };ptrB.reset(); //只是修改指针的指向,并不释放指针内存地址std::cout << ptrB << std::endl;ptrA.reset();std::cout << ptrA << std::endl;std::cout << ptrC << std::endl;ptrC.reset(); //释放智能指针的内存地址std::cout << ptrC << std::endl;}