c++智能指针(unique_ptr)

2022-11-13  本文已影响0人  arkliu

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

智能指针的分类

unique_ptr

unique_ptr的三种创建方式

unique_ptr创建

cat.h

#ifndef CAT_H
#define CAT_H
#include<string>
#include<iostream>
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"};
};    
#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 <iostream>
#include <memory>
#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<Cat> uc_p2(c_p2);
    uc_p2->cat_info();

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

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

get()方法返回裸指针

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

class Test {

};

int main() {
    Test* test = new Test(); // 定义原始指针test,并分配内存
    unique_ptr<Test>test_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

void do_with_cat_pass_value(unique_ptr<Cat> c) {
    c->cat_info();
}


unique_ptr<Cat>uc_p1 = make_unique<Cat>("hello..");
do_with_cat_pass_value(std::move(uc_p1));
do_with_cat_pass_value(make_unique<Cat>("world.."));
void do_with_cat_pass_ref(unique_ptr<Cat> &c) {
    c->set_name("hhhhhhh");
    c->cat_info();
    c.reset();
}

unique_ptr<Cat>uc_p2 = make_unique<Cat>("hello..");
do_with_cat_pass_ref(uc_p2);
cout << "uc_p2 address is :"<<uc_p2.get()<<endl;
image.png
unique_ptr<Cat> get_unique_ptr() {
    unique_ptr<Cat> p_cat = make_unique<Cat>("nmnm");
    return p_cat;
}

get_unique_ptr()->cat_info();

\color{red}{不支持指针的运算(+, -, ++, --)}

用nullptr赋值给unique_ptr将释放对象

#include <iostream>
#include <memory>
#include<string>
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<Cat> pu(new Cat("tony"));
    cout <<"赋值前:"<<endl;
    if (pu != nullptr)
    {
        cout <<"pu 不是空的"<<endl;
    }
    pu = nullptr;
    if (pu == nullptr)
    {
        cout <<"pu 是空的"<<endl;
    }
    
    return 0;
}
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> &cat_ptr) {
    cout << cat_ptr->get_name() << endl;
}

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

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

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

reset()释放对象

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

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

void swap(unique_ptr<T> &right);

unique_ptr不是绝对安全

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

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

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

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


image.png

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


image.png

unique_ptr支持数组

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

猜你喜欢

热点阅读