unique_ptr使用详解(介绍,场景,方法,实例)

1.什么是uniqueptr

uniqueptr是智能指针的一种,主要用于C++的内存申请和释放,因为C++在申请内存后,要手动进行delete,这样就会出现有时候忘记delete,或者return,break,异常等原因没有执行到delete,如下面的代码所示,new了一个A的对象,要时刻注意delete销毁对象,而且如果是new了多个对象,需要同时注意什么时候销毁什么对象,return,break,异常等情况都要考虑,所以这就给开发造成很大的困扰。不知道什么时候delete内存,所以引入uniqueptr指针,当指针销毁不时,自动删除指针指向的内存。unique_ptr的特点是只允许一个指针指向这块内存,unique_ptr赋值操作是不允许的,例如uniqueptr1=uniqueptr2;是不允许的,只能通过转移,uniqueptr1=move(uniqueptr2);将uniqueptr2指向的内存转移给uniqueptr1。:可以从一个函数中返回一个unique_ptr;

复制代码
#include <memory>
#include<iostream>
using namespace std;

class A {};
int main()
{
    A* ptrA = new A;
    try
    {
    if()
    {  
      delete ptrA;
      return -1;
    }
    
//... //... //... //... //... } catch (...) { delete ptrA; //1 throw; } delete ptrA; //2 return 0; }
复制代码

 

2.使用方法

上面的代码如果用uniqueptr就方便很多,只要申请unique_ptr指针指向内存,ptrA的作用域结束后销毁,会自动销毁ptrA 指向的内存;不用再去关注什么时候销毁内存;

复制代码
#include <memory>
#include<iostream>
using namespace std;

class A {};
int main()
{
    unique_ptr<A> ptrA = make_unique<A>();
  //unique_ptr<A> ptrA(new A);//第二种方式
try {     if()     {         //.....       return -1;     }      //... //... //... //... //... } catch (...) { throw; } return 0; }
复制代码

3.详细介绍

复制代码
#include "stdafx.h"

#include <iostream>
using namespace std;
#include <string>
#include <memory>

int main()
{
    
        unique_ptr<int> uptr1 = make_unique<int>();//新建第一个对象
        //unique_ptr<int> uptr2 = uptr1;//错误,唯一指向,不能赋值给其他指针
        unique_ptr<int> uptr2 = move(uptr1);//将指针uptr1指向的内存转移给uptr2,uptr1变为空
        unique_ptr<int> uptr3= make_unique<int>();//新建第二个对象
        int* p4 = uptr3.get();//返回指针uptr3指向的对象,可以修改对象的值,但是不能执行delete p4;否则uptr3销毁时释放内存会报错;
        *p4 = 8;//修改内存保存的值
        //delete p4;//会报错如下图所示,这里销毁一次,uptr3又销毁一次;
        uptr3.release();//释放uptr3指向内存,但是不销毁内存;
        unique_ptr<int> uptr4(new int);//新建第三个对象
        uptr4.reset();//清空uptr4指向,并且销毁指向内存;
        unique_ptr<int> uptr5(new int);//新建第四个对象;
        uptr5.reset(new int);//新建第五个对象,uptr5指向第五个对象,并销毁第四个对象内存;
        unique_ptr<int> uptr6;
        uptr6.reset(new int);//新建第六个对象,uptr6指向第六个对象
return 0; }
复制代码

 

 

 

使用unique_ptr需要包含头文件:

#include<memory>

 

创建和初始化

复制代码
#include <iostream>
#include <memory>
using namespace std;

int mian()
{
    unique_ptr<int> p; // 可以指向int对象的一个空智能指针
    unique_ptr<int> p(new int(105)); // p指向一个值为105的int对象
    auto p(new int(105)); // 不能简写为auto,这里auto推断出是普通指针
  unique_ptr<int> p = make_unique<int>(100);//C14才出现make_unique
  auto p = make_unique<int>(200);

}
复制代码

 

但是,release函数会取消unuque_ptr对内存的管理,但是不会删除内存,需要手动删除release取消管理的内存,如果我们不用另一个智能指针来保存release() 返回的指针,我们的程序就要负责资源的释放,否则就会有内存泄漏

复制代码
#include <iostream>
#include <memory>
using namespace std;

int mian()
{
    unique_ptr<string> p1(new string("hello"));
    // release()返回p1当前保存的指针,并将p1置为空。p2被初始化为p1原来保存的指针,即将所有权从p1转移给p2
    unique_ptr<string> p2(p1.release());
}
复制代码

reset取消内存管理,同时删除内存

复制代码
#include <iostream>
#include <memory>
using namespace std;

int mian()
{
    unique_ptr<string> p1(new string("hello"));
    p1.reset();//删除内存
}
复制代码

reset带参数,则是指向新内存,删除旧内存

复制代码
#include <iostream>
#include <memory>
using namespace std;

int mian()
{
    unique_ptr<string> p1(new string("hello"));
    p1.reset(new string("world"));
}
复制代码

get返回智能指针指向的内存指针,依赖修改内存存储的值

复制代码
#include <iostream>
#include <memory>
using namespace std;

int mian()
{
    unique_ptr<string> up(new string("hello"));
    string* p = up.get();
    *p = "world";
}
复制代码

 自定义删除器,删除器会在 unique_ptr 被销毁时调用,可以是函数指针、函数对象或lambda表达式*。通常,使用lambda表达式来定义自定义删除器是比较方便的。

自定义删除器的应用场景:

对于需要特殊处理的资源,如大内存块、缓存等,自定义删除器可以提供更高效的内存管理方式。
对于特定资源,如文件句柄、数据库连接等,使用自定义删除器可以确保资源的正确释放和管理。
通过使用自定义删除器,std::unique_ptr能够在释放资源时执行特定的清理操作,从而帮助节省内存并提升性能

void customDeleter(int* ptr) {  
    // 自定义删除逻辑  
    delete ptr;  
}  
  
std::unique_ptr<int, decltype(&customDeleter)> ptr(new int(5), customDeleter);
复制代码
#include <iostream>
#include <memory>
using namespace std;

void customDeleter(string* ptr)
{
    delete ptr;
    ptr = nullptr;
}

int main()
{
    // 使用using
    using cus_del = void(*)(string*);
    unique_ptr<string, cus_del> uni_ptr(new string("hello"),customDeleter);

    // 使用 lambda
    auto my_del = [](string* ptr)->{
    delete ptr;
    ptr = nullptr;
    }
    unique_ptr<string, decltype(my_del)> uni_ptr(new string("hello"),my_del    );
}
复制代码

 

posted @   一字千金  阅读(2955)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示