c++ unique_ptr

 智能指针概述

C++的指针包括原始指针和智能指针两种,智能指针是原始指针的封装,其优点是可以自动分配内存,无需担心内存的泄露。

并不是所有的指针都可以封装为智能指针,很多时候原始指针要更方便;

各种指针里,原始指针最常用,其次是unique_ptr和shared_ptr,weak_ptr是对shared_ptr的补充,应用场景较少。

智能指针只能解决一部分问题:独占/共享所有权指针的释放和传输;并没有从根本上解决C++的内存泄漏问题 

 

独占指针 unique_ptr
在给定的时刻,只能有一个指针管理内存,当指针超出作用域后,内存自动释放

该类型指针不可Copy,只可以Move

uniqueptr是智能指针的一种,主要用于C++的内存申请和释放,因为C++在申请内存后,要手动进行delete,这样就会出现有时候忘记delete,或者return,break,异常等原因没有执行到delete,不知道什么时候delete内存,所以引入uniqueptr指针,当指针销毁不时,自动删除指针指向的内存。unique_ptr的特点是只允许一个指针指向这块内存,unique_ptr赋值操作是不允许的,例如uniqueptr1=uniqueptr2;是不允许的,只能通过转移,uniqueptr1=move(uniqueptr2);将uniqueptr2指向的内存转移给uniqueptr1。 

  • unique_ptr可以通过get获取地址,
  • 通过->调用成员函数,
  • 通过* (解引用)

创建方式

(1)通过已有的裸指针创建(建议裸指针设为空,并且及时销毁,不推荐)

示例:

复制代码
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include<Windows.h>  
using namespace std; 

//自定义数据类型
class Person {
public:
    Person(string name, int age) {
        mName = name;
        mAge = age;
    }

    Person();

    void Set_Name(string name)
    {
        this->mName = name;
    }

    void Info()
    {
        std::cout << "name:" << this->mName << endl;
    }

public:
    string mName;
    int mAge;
};
 
int main() { 
    Person* p1 = new Person();
    unique_ptr<Person> uc1{ p1 };
    p1->Set_Name("哈哈");
    uc1->Info();
    // 这种方式需要再删除裸指针
    delete p1;
    p1 = nullptr; 
    uc1->Info();  
    system("pause");

    return 0;
}

Person::Person()
{
}
复制代码

 

 

(2)通过new创建

示例:

复制代码
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include<Windows.h>  
using namespace std;


//自定义数据类型
class Person {
public:
    Person(string name, int age) {
        mName = name;
        mAge = age;
    }

    Person();

    void Set_Name(string name)
    {
        this->mName = name;
    }

    void Info()
    {
        std::cout << "name:" << this->mName << endl;
    }

public:
    string mName;
    int mAge;
};
 
int main() { 
    unique_ptr<Person> uc2(new Person);
    uc2->mAge = 11;
    uc2->mName = "uc2";
    uc2->Info(); 
    system("pause"); 
    return 0;
}

Person::Person()
{
}
复制代码

 结果:

 

(3)通过std::make_unique创建(推荐)

示例:

复制代码
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include<Windows.h>  
using namespace std;


//自定义数据类型
class Person {
public:
    Person(string name, int age) {
        mName = name;
        mAge = age;
    }

    Person();

    void Set_Name(string name)
    {
        this->mName = name;
    }

    void Info()
    {
        std::cout << "name:" << this->mName << endl;
    }

public:
    string mName;
    int mAge;
};
 
int main() {  
    unique_ptr<Person> uc2 =make_unique<Person>();
    uc2->mAge = 11;
    uc2->mName = "uc2";
    uc2->Info(); 
    system("pause"); 
    return 0;
}

Person::Person()
{
}
复制代码

 

unique_ptr和函数调用

 补充:还是尽量使用引用传递

 值传递

 通过move方式实现 

示例:

复制代码
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include<Windows.h>  
using namespace std;


//自定义数据类型
class Person {
public:
    Person(string name, int age) {
        mName = name;
        mAge = age;
    }

    Person();

    void Set_Name(string name)
    {
        this->mName = name;
    }

    void Info()
    {
        std::cout << "name:" << this->mName << endl;
    }

public:
    string mName;
    int mAge;
};

void pass_value(unique_ptr<Person> u)
{
    u->mName = "值传递";
    u->Info();
}

int main() {
    unique_ptr<Person> uc2 = make_unique<Person>();
    //  将指针uc2指向的内存转移给u,uc2变为空
    pass_value(move(uc2)); 
    // 下面代码报错,因为已经指向空了
    //uc2->Info();
    system("pause");
    return 0;
} 
Person::Person()
{
}
复制代码

 

结果:

 

引用传递

示例:

复制代码
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include<Windows.h>  
using namespace std;


//自定义数据类型
class Person {
public:
    Person(string name, int age) {
        mName = name;
        mAge = age;
    }

    Person();

    void Set_Name(string name)
    {
        this->mName = name;
    }

    void Info()
    {
        std::cout << "name:" << this->mName << endl;
    }

public:
    string mName;
    int mAge;
};

// 加const,防止调用unique_ptr的函数,比如说reset,因为执行之后会清空u指向,并且销毁指向内存;
void pass_ref(const  unique_ptr<Person>& u)
{
    u->mName = "值传递";
    u->Info();
    // 加const之后无法执行下面代码了 
    //u.reset();
}

int main() {
    unique_ptr<Person> uc2 = make_unique<Person>();
    pass_ref(uc2);
    uc2->Info();
    system("pause");
    return 0;
}

Person::Person()
{
}
复制代码

结果:

 

还有一种定义别名的方式,这个纯粹是看个人的代码风格了

复制代码
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include<Windows.h>  
using namespace std;


//自定义数据类型
class Person {
public:
    Person(string name, int age) {
        mName = name;
        mAge = age;
    }

    Person();

    void Set_Name(string name)
    {
        this->mName = name;
    }

    void Info()
    {
        std::cout << "name:" << this->mName << endl;
    }

    // 在这里定义一个unique_ptr的别名UniquePtr
    using UniquePtr = unique_ptr<Person>;
public:
    string mName;
    int mAge;
};

// 加const,防止调用unique_ptr的函数,比如说reset,因为执行之后会清空u指向,并且销毁指向内存;
void pass_ref(const  unique_ptr<Person>& u)
{
    u->mName = "值传递";
    u->Info();
    // 加const之后无法执行下面代码了 
    //u.reset();
}

int main() { 
    Person::UniquePtr client = make_unique<Person>();
    client->Info();
    system("pause");
    return 0;
}

Person::Person()
{
}
复制代码

  

posted @   安静点--  阅读(713)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示