智能指针笔记


智能指针(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 <iostream>
#include <string>
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;
}

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

	Student* s = new Student("张三");
	unique_ptr<Student> s1{s};
	delete s;
	s1->Student_info();
	s1->Student_info();
	return 0;

2. 通过new来创建:

	unique_ptr<Student> s1{new Student("小王")};
	s1->Student_info();
	s1->Set_name("小李");
	s1->Student_info();
	return 0;

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

unique_ptr<Student> s1 = make_unique<Student>();
	s1->Student_info();
	s1->Set_name("小李");
	s1->Student_info();
	return 0;

在这里插入图片描述

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;
}

因为独占的特性,该类型指针不可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;
}

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

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;
}

在这里插入图片描述

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;
}

在这里插入图片描述
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;
}

在这里插入图片描述

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;
}

在这里插入图片描述

weak_ptr

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值