C++ unique_ptr简单使用

#######################智能指针(智能指针是存储指向动态分配(堆)对象指针的类,用于生存期控制,能够确保在离开指针所在作用域时,自动正确的销毁动态分配的对象,防止内存泄漏)
头文件#include <memory>
unique_ptr特性 (属性为对象, 而不是指针, 管理指针)
(1).基于排他所有权模式:两个指针不能指向同一个资源
无法进行左值unique_ptr复制构造,也无法进行左值复制赋值操作,但允许临时右值赋值构造和赋值
保存指向某个对象的指针,当它本身离开作用域时会自动释放它指向的对象。
在容器中保存指针是安全的
无法进行左值复制赋值操作,但允许临时右值赋值构造和赋值, 结合std::move()使用, 将一个

(2). unique_ptr做为STL容器的元素时,不能作为类的成员变量; share_ptr可以作为类成员嵌套使用
例如:

class b{
private:
vector<unique_ptr<int>> temp; //错误
vector<unique_ptr<a>> tmp; //错误
}

(3). unique_ptr做为STL容器的元素时,不能直接进行传递,因为不可以进行拷贝和赋值操作.
vector<unique_ptr<int>> a;
a.push_back(new int(20)); //错误
a.emplace_back(new int(20)); //错误
a.emplace_back(make_unique<int>(20)); //错误

 


方法:
1. get(); // 返回对象管理的裸指针,带有风险性
2. release(); // 释放,调用后智能指针和其所指向对象的联系再无联系,但是该内存仍然存在有效。它会返回裸指针,但是该智能指针被置空。
返回的裸指针我们可以手工delete来释放,也可以用来初始化另外一个智能指针,或者给另外一个智能指针赋值。
3. reset();
reset()不带参数情况:释放智能指针所指向的对象(释放因为它是独占,而不像shared_ptr还需要考虑引用计数),并将智能指针置空。
reset()带参数时:释放智能指针所指向的对象,并将该智能指针指向新对象。

4. swap(); // 交换智能指针


例如:
unique_ptr<string> pointer(new string("123456"));
unique_ptr<string> pointer2(new string("888888"));

pointer = pointer2; // 非法, 禁止左值赋值操作
unique_ptr<string> pointer3(pointer2); // 禁止左值赋值构造

unique_ptr<string> p3(std::move(p1)); // 合法, std::move()将左值改变成右值
p1 = std::move(p2); // 使用move把左值转成右值就可以赋值了,效果和auto_ptr赋值一样

简单代码例子:

复制代码
#include <iostream>
#include <string>
#include <memory>
#include <stdio.h>
#include <stdlib.h>
#include <vector>

using namespace std;

class Absobj
{
public:
    Absobj()
    {
        printf("Create Abs - address: %p\n", this);
    }

    void print()
    {
        printf("Absobj print------\n");
    }

    ~Absobj()
    {
        printf("~Del AbsObj - address: %p\n", this);
    }

    char *pBuf = nullptr;
    int m_num = 0;
};


unique_ptr<Absobj> createPoint(int num)
{
    unique_ptr<Absobj> ptr(new Absobj);
    printf("ptr: %p\n", &ptr);
    ptr->m_num = num;
    return ptr;
}

void dowork(std::unique_ptr<Absobj> &&ptr)
{
    printf("ptr: %d\n", ptr->m_num);
    ptr->m_num = 888;
}

void gowork(std::unique_ptr<Absobj> ptr)
{
    printf("-->ptr: %d\n", ptr->m_num);
}

void towork(std::unique_ptr<Absobj> &ptr)
{
    printf(">>>ptr: %d\n", ptr->m_num);
}

int main(void)
{
    vector<unique_ptr<Absobj>> vec;

    unique_ptr<Absobj> ptr(new Absobj);
    ptr->m_num = 123;
    printf("ptr address: %p | num: %d\n", &ptr, ptr->m_num);

    dowork(std::move(ptr));         // 二级引用做参数,操作的是本身,std::move不会释放智能指针对象
    if ( ptr == nullptr )
    {
        printf("Ptr is Null.\n");
    }

    towork(ptr);                    // 引用传递,智能指针直接做为参数,可不用作为右值传递,
    if ( ptr == nullptr )
    {
        printf("===Ptr is Null.\n");
    }

    //gowork(std::move(ptr));         // 值传递, 不能直接传递左值(unique_ptr不支持拷贝赋值),只能转换成右值传递
    if ( ptr == nullptr )
    {
        printf(">>>Ptr is Null.\n");
    }    
     return 0;    
}
复制代码

程序运行情况:

 

类中嵌套智能指针使用:

复制代码
#include <iostream>
#include <string>
#include <memory>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <mutex>
#include <list>
#include <mutex>
#include <algorithm>
#include <memory>
#include <atomic>
#include <assert.h>

using namespace std;

// 自定义对象
class Test
{
public:
    Test(const string &str=string())
    {
        cout << "Create Test" << endl;
        m_str = string("test") + str;
    }
    ~Test()
    {
        cout << "~Del Test()" << endl;
    }

    string m_str;
};

class Son
{
public:
    Son(const string &str=string(), int num=0): m_str(std::move(str)) , m_num(num)
    {
        printf("Create Son\n");
        m_unptr.reset(new Test(str));
    }

    ~Son()
    {
        printf("~Del Son\n");
    }

    string m_str = string();
    int m_num = 0;
    unique_ptr<Test> m_unptr;
};

/**
 * @brief The DataMng class         增删改查
 */
class DataMng
{
public:
    DataMng(){}

    void add(const string &str, int num)
    {
        m_uniptrVec.push_back(unique_ptr<Son>(new Son(str, num)));
    }

    // 根据条件删除指定的对象
    void del(int num)
    {
        for ( auto iter = m_uniptrVec.begin(); iter != m_uniptrVec.end(); )
        {
            if ( (*iter).get() == nullptr )
                continue;

            if ( (*iter)->m_num == num )
            {
                printf("earse address: %p | num: %d | str: %s\n", (*iter).get(), (*iter)->m_num, (*iter)->m_str.c_str());
                iter = m_uniptrVec.erase(iter);
            }else
            {
                iter++;
            }
        }
    }

    // 直接删除指定对象
    void del(unique_ptr<Son> &ptr)
    {
        auto iter = std::find(m_uniptrVec.begin(),m_uniptrVec.end(), ptr);
        if ( iter != m_uniptrVec.end() )
        {
            printf("del.\n");
            iter = m_uniptrVec.erase((iter));
        }
    }
  // 删除全部
    void del()
    {
        auto iter = m_uniptrVec.begin();
        while( iter != m_uniptrVec.end() )
        {
            iter = m_uniptrVec.erase(iter);
        }
    }

    // 更新数据
    void update(int num, const string &str)
    {
        for ( auto iter = m_uniptrVec.begin(); iter != m_uniptrVec.end(); )
        {
            if ( (*iter).get() == nullptr )
                continue;
            if ( (*iter)->m_num == num )
            {
                (*iter)->m_str = str;
                (*iter)->m_unptr->m_str= str;
                break;
            }else{
                iter++;
            }
        }
    }

    // 根据条件查找智能指针对象的裸指针(返回裸指针, 有风险)
    Son *find(int num)
    {
        for ( auto iter = m_uniptrVec.begin(); iter != m_uniptrVec.end(); )
        {
            if ( (*iter).get() == nullptr )
                continue;
            if ( (*iter)->m_num == num )
            {
                return (*iter).get();           // 返回裸指针, 有风险
            }else{
                iter++;
            }
        }
        return nullptr;
    }

    // 智能指针容器
    vector<unique_ptr<Son>> &uniptrVec()
    {
        return m_uniptrVec;
    }

    // 打印信息
    void printVec()
    {
        for ( auto &obj: m_uniptrVec )
        {
            printf("address: %p | num: %d | str: %s | tstr: %s\n", obj.get(), obj->m_num, obj->m_str.c_str(), obj->m_unptr.get()->m_str.c_str());
        }
        printf("\n");
    }

private:
    vector<unique_ptr<Son>> m_uniptrVec;
};

/**
 * @brief main              智能指针测试
 * @return
 */
int main(void)
{
    DataMng dataMng;
    printf(">>>>>>>>>>>>>>>>Add\n");
    //
    for (int i=0; i<4; i++)
    {
        dataMng.add(std::to_string(i), i);
    }
    dataMng.printVec();

    //
    printf(">>>>>>>>>>>>>>>>Changed\n");
    dataMng.update(2, string("88888888"));
    dataMng.printVec();

    //
    printf(">>>>>>>>>>>>>>>>Find\n");
    auto ptr = dataMng.find(2);
    printf("find ptr: %p | num: %d | str: %s\n", &ptr, ptr->m_num, ptr->m_str.c_str());
    dataMng.update(ptr->m_num, string("22222222"));
    dataMng.update(1, string("1111111111111"));
    dataMng.printVec();

    //
    printf(">>>>>>>>>>>>>>>>Del\n");
    dataMng.del(dataMng.uniptrVec()[0]);
    dataMng.printVec();

    dataMng.del(1);
    dataMng.printVec();

    printf("End uniptrVec.size: %d\n", (int)dataMng.uniptrVec().size());
    return 0;
}
复制代码

执行结果:

 

posted @   蔡头一枚  阅读(697)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
点击右上角即可分享
微信分享提示