• 智能指针笔记



    智能指针(RAII)是对普通指针进行的一层封装。这样使得智能指针的行为动作像一个指针,本质上却是一个对象,这样可以方便管理一个对象的生命周期。

    指针创建后忘记删除,或者删除的情况没有考虑清楚,容易造成悬挂指针或者说野指针。

    原理RALL:构造的时候分配和创建被管理对象,析构的时候销毁和释放被管理对象,不用担心潜在的内存泄漏

    unique_ptr

    unique_ptr接口:
    在这里插入图片描述
    unique_ptr是对裸指针的封装,存储着一个指针和一个删除器
    · 函数对象(函数的指针,仿函数,闭包,std::function)
    · 函数对象的左值引用
    · 函数的左值引用

    unique_ptr在任何给定时刻,只能有一个指针管理内存,当指针超出作用域时,内存将自动释放,该类型指针不可Copy,只可以Move

    创建方式:

    1. 通过已有的裸指针创建
    2. 通过new来创建
    3. 通过std::make_unique创建(推荐)
      unique_ptr可以通过get()获取地址
      unique_ptr实现了->与*:可以通过->调用成员函数;可以通过*调用dereferencing

    1. 通过已有的裸指针创建:

    #include 
    #include 
    using namespace std;
    
    class Student
    {
    public:
    	Student() = default;
    	Student(string name);
    	~Student();
    	void Student_info() const;
    	string Student_get() const;
    	void Set_name(const string& name);
    private:
    	string name;
    };
    Student::Student(string name) :name(name)
    {
    	cout << "构造函数已运行" << endl;
    }
    Student::~Student()
    {
    	cout << "析构函数已运行" << endl;
    }
    void Student::Student_info() const
    {
    	cout << name << endl;
    }
    string Student::Student_get() const
    {
    	return name;
    }
    void Student::Set_name(const string& name)
    {
    	this->name = name;
    }
    
    
    int main() {
    	Student* s = new Student("张三");
    	unique_ptr<Student> s1{s};
        
    	s->Student_info();
    	s1->Student_info();
    
    	s->Set_name("李四");
    	s1->Student_info();
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    在这里插入图片描述
    这样无法独占,需要提前delete

    	Student* s = new Student("张三");
    	unique_ptr<Student> s1{s};
    	delete s;
    	s1->Student_info();
    	s1->Student_info();
    	return 0;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2. 通过new来创建:

    	unique_ptr<Student> s1{new Student("小王")};
    	s1->Student_info();
    	s1->Set_name("小李");
    	s1->Student_info();
    	return 0;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述
    3. 通过std::make_unique创建(推荐):

    unique_ptr<Student> s1 = make_unique<Student>();
    	s1->Student_info();
    	s1->Set_name("小李");
    	s1->Student_info();
    	return 0;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    unique_ptr与函数调用

    void get(unique_ptr<Student> s)
    {
    	s->Set_name("小八");
    }
    
    
    int main() {
    	unique_ptr<Student> s = make_unique<Student>();
    	s->Set_name("小李");
    
    	get(s);//报错无法调用
    	s->Student_info();
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    因为独占的特性,该类型指针不可Copy,所以不能直接调用。

    解决方式使用move,但是move将主函数的指针转到了函数中,当函数作用域结束后会自动析构,主函数无法再用这个指针了。

    
    void get(unique_ptr<Student> s)
    {
    	s->Set_name("小八");
    	s->Student_info();
    }
    
    
    int main() {
    	unique_ptr<Student> s = make_unique<Student>();
    	s->Set_name("小李");
    
    	get(move(s));
    	//s->Student_info();报错因为该指针被move了
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    由于这个特性所以可以使用引用传值

    void get(unique_ptr<Student>& s)
    {
    	s->Set_name("小八");
    	
    }
    
    
    int main() {
    	unique_ptr<Student> s = make_unique<Student>();
    	s->Set_name("小李");
    	s->Student_info();
    	get(move(s));
    	s->Student_info();
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述

    shared_ptr

    shared_ptr:技术指针又称共享指针,与unique_ptr不同它是可以共享数据的

    · shared_ptr创建了一个计数器与类对象所指的内存相关联

    · Copy则计数器加一,销毁则计数器减一

    · api为use_count()

    
    int main() {
    
    	shared_ptr<int> i = make_shared<int>(100);
    
    	cout << "value : " << i << endl;
    	cout << "count : " << i.use_count() << endl;
    
    	shared_ptr<int> L = i;
    	cout << "count : " << i.use_count() << endl;
    	cout << "count : " << L.use_count() << endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述
    shared_ptr

    shared_ptr可以直接复制调用,不用move,但是计数器会加一,直接引用传值不会计数器不会增加,函数运行结束后复制的指针会销毁,所以回到主函数后count会变回原来的数量。

    void get(shared_ptr<Student> m, shared_ptr<Student>& n)
    {
    	cout << "copy传值 :" << m.use_count() << endl;
    	cout << "ref传值 :" << n.use_count() << endl;
    }
    
    
    int main() {
    
    	shared_ptr<Student> m = make_shared<Student>();
    	shared_ptr<Student> n = make_shared<Student>();
    	m->Set_name("张三");
    	n->Set_name("李四");
    	cout << "copy之前 :" << m.use_count() << endl;
    	cout << "ref之前 :" << n.use_count() << endl;
    	get(m, n);
    	cout << "copy之后 :" << m.use_count() << endl;
    	cout << "ref之后 :" << n.use_count() << endl;
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在这里插入图片描述

    shared_ptr与unique_ptr

    1. shared_ptr不能转为unique_ptr
    2. unique_ptr可以转为 shared_ptr

    常见设计:将函数返回值设置为unique_ptr是一种常见的设计模式,这样可以提高代码的复用度,因为unique_ptr可以随时转为 shared_ptr。

    int main() {
    
    	unique_ptr<Student> m = make_unique<Student>();
    	shared_ptr<Student> n = make_shared<Student>();
    	m->Set_name("张三");
    	n = move(m);
    	n->Student_info();
    	cout << n.use_count() << endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述

    weak_ptr

    weak_ptr用来解决循环依赖的问题

  • 相关阅读:
    springboot启动流程
    Vue、jquery和angular之间区别
    ORACLE表空间说明及操作
    扬帆出海,拒做云内卷王?
    老嫂子的保姆级科普 选择视频剪辑软件就从阅读本文开始
    ERP系统有哪些优点和缺点?
    HNSW-分层可导航小世界 算法学习
    阅读LINGO-1: Exploring Natural Language for Autonomous Driving
    C++ Reference: Standard C++ Library reference: C Library: cstring: strcspn
    07OpenCV 图像模糊
  • 原文地址:https://blog.csdn.net/weixin_44971209/article/details/126158508