c++智能指针(unique_ptr)

在c++11中通过引入只能指针的概念,使得c++程序猿不需要手动释放内存

智能指针的分类

  • std::unique_ptr
  • std::shared_prt
  • std::weak_ptr
    注意:
    std::auto_ptr已被废弃

unique_ptr

  • unique_ptr 在任何给定的时刻,只能由一个指针管理内存
  • 当指针超出作用域时,内存将自动释放
  • 该类型指针不可copy,只能move

unique_ptr的三种创建方式

  • 通过已有裸指针创建

  • 通过new创建

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

  • unique_ptr可以通过get()获取地址

  • unique_ptr实现了->与*
    即可以通过->调用成员函数
    可以通过* 调用解引用

unique_ptr创建

cat.h

#ifndef CAT_H
#define CAT_H
#include
#include
using namespace std;
class Cat {
    public:
        Cat(string name);
        Cat() = default;
        ~Cat();

        void cat_info()const{
            cout << "cat ino name:"<name = name;
        }

    private:
        string name{"mimi"};
};    
#endif

cat.cpp

#include "cat.h"

Cat::Cat(string name) :name(name) {
     cout << "constructor of cat  " << name<< endl;
}

Cat::~Cat() {
    cout << "Deconstructor of cat  " << name << endl;
}
#include 
#include 
#include "cat.h"
using namespace std;

int main() {
    // 栈上分配
    Cat c1("ok");
    c1.cat_info();

    // 堆上分配,裸指针
    Cat * c_cp1 = new Cat("yy");
    c_cp1->cat_info();
    delete c_cp1;

    //------第一种  用已经存在的地址初始化智能指针  不推荐-----
    Cat * c_p2 = new Cat("tts");
    unique_ptr uc_p2(c_p2);
    uc_p2->cat_info();

    //------第二种-----
    unique_ptruc_p3{new Cat("dd")};
    uc_p3->cat_info();
    uc_p3->set_name("oo");
    uc_p3->cat_info();

    //------第三种 c++14标准 推荐使用-----
    unique_ptruc_p4 = make_unique();
    uc_p4->cat_info();
    uc_p4->set_name("oo");
    uc_p4->cat_info();
    return 0;
}

get()方法返回裸指针

#include
#include
#include
using namespace std;

class Test {

};

int main() {
    Test* test = new Test(); // 定义原始指针test,并分配内存
    unique_ptrtest_ptr(test);  // 创建智能指针test_ptr,用于管理原始指针test
    cout << "         裸指针的值:" << test << endl;
    cout << "test_ptr.get()的值:" << test_ptr.get() << endl;
    cout << "    test_ptr的地址:" << &test_ptr << endl;
    return 0;
}
image.png

函数调用与unique_ptr

  • 值传递
    需要用std::move来转移内存的拥有权
    如果参数直接传入std::make_unique语句,自动转换为move
void do_with_cat_pass_value(unique_ptr c) {
    c->cat_info();
}


unique_ptruc_p1 = make_unique("hello..");
do_with_cat_pass_value(std::move(uc_p1));
do_with_cat_pass_value(make_unique("world.."));
  • 引用传递
    如果设置参数为const则不能改变指向
    比方说reset()
  • reset()方法为智能指针清空方法
void do_with_cat_pass_ref(unique_ptr &c) {
    c->set_name("hhhhhhh");
    c->cat_info();
    c.reset();
}

unique_ptruc_p2 = make_unique("hello..");
do_with_cat_pass_ref(uc_p2);
cout << "uc_p2 address is :"<
image.png
  • 值返回
    指向一个local object
    可以用做链式函数
unique_ptr get_unique_ptr() {
    unique_ptr p_cat = make_unique("nmnm");
    return p_cat;
}

get_unique_ptr()->cat_info();

用nullptr赋值给unique_ptr将释放对象

#include 
#include 
#include
using namespace std;

class Cat {
    public:
        Cat(string name);
        Cat() = default;
        ~Cat();

        void cat_info()const{
            cout << "cat ino name:" << name << endl;
        }

        string get_name() const {
            return name;
        }

        void set_name(const string &name) {
            this->name = name;
        }

    private:
        string name{"mimi"};
};  

Cat::Cat(string name) :name(name) {
     cout << "constructor of cat  " << name<< endl;
}

Cat::~Cat() {
    cout << "Deconstructor of cat  " << name << endl;
}

int main() {
    unique_ptr pu(new Cat("tony"));
    cout <<"赋值前:"<
image.png

release释放对原始指针的控制权

release释放对原始指针的控制权,将unique_ptr置为空,返回裸指针

// 函数fun1需要使用指针,但是不对这个指针负责
void fun1(const Cat* cat_ptr) {
    cout << cat_ptr->get_name() << endl;
}

// 函数fun2需要使用指针,并且会对这个指针负责
void fun2(const Cat* cat_ptr) {
    cout << cat_ptr->get_name() << endl;
    delete cat_ptr;
}

// 函数fun3需要使用指针,但是不对这个指针负责
void fun3(const unique_ptr &cat_ptr) {
    cout << cat_ptr->get_name() << endl;
}

// 函数fun4需要使用指针,并且会对这个指针负责
void fun4(const unique_ptr cat_ptr) {
    cout << cat_ptr->get_name() << endl;
}

int main() {
    unique_ptr pu(new Cat("tony"));
    // fun1(pu.get());
    // fun2(pu.release());

    fun4(std::move(pu));
    if (pu == nullptr)
    {
        cout <<"pu 是空指针"<

reset()释放对象

pp.reset()  //释放pp对象指向的资源对象
pp.reset(nullptr)  //释放pp对象指向的资源对象
pp.reset(new Cat("jerry"))  //释放pp对象指向的资源对象,同时指向新对象

swap() 交换两个unique_ptr的控制权

void swap(unique_ptr &right);

unique_ptr不是绝对安全

unique_ptr不是绝对安全,如果程序调用exit()退出, 全局的unique_ptr可以自动释放,但是局部的unique_ptr无法释放。

unique_ptr pu(new Cat("全局的猫"));

int main() {
    unique_ptr pu(new Cat("局部的猫"));
    return 0;
    //exit(0);
}

此时程序结束,全局的和局部的都被释放了


image.png

将上面的退出方式,改为exit,局部的对象就不会被释放


image.png

unique_ptr支持数组

int main() {
    // unique_ptr pu(new Cat[2]);
    unique_ptr pu(new Cat[2] {string("狸猫"), string("家猫")});
    cout << pu[0].get_name() << "===" << pu[1].get_name()<< endl;
    return 0;
}
image.png

你可能感兴趣的:(c++智能指针(unique_ptr))