前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >再探 智能指针

再探 智能指针

作者头像
看、未来
发布2021-10-20 16:55:47
2610
发布2021-10-20 16:55:47
举报
请添加图片描述
请添加图片描述

使用任何一项工具,都需要承担代价与风险的。

1、一个裸的指针不要用两个shared_ptr管理,unique_ptr也是,它们都会认为自己独占这个资源,你等释放的时候试试看。

2、用weak_ptr打破循环引用。

3、当需要在类的内部接口中,如果需要将this作为智能指针来使用的话,需要用该类派生自enable_shared_from_this。 enable_shared_from_this和shared_from_this在构造和析构中是不能使用的,在某些情况下也不能使用,因为构造的时候类还未生成好,析构的时候类快完蛋了都没有意义。

代码语言:javascript
复制
#include <cassert>
#include <memory>
#include <iostream>

class Parent;

typedef std::shared_ptr<Parent> ParentPtr;
typedef std::weak_ptr<Parent> WeakParentPtr;

class Child : public std::enable_shared_from_this<Child> {
public:
	WeakParentPtr father;
	~Child();
	Child();
	void checkRelation();
};

typedef std::shared_ptr<Child> ChildPtr;
typedef std::weak_ptr<Child> WeakChildPtr;

class Parent : public std::enable_shared_from_this<Parent> {
public:
	WeakChildPtr son;
	~Parent();
	Parent();
	void checkRelation();
};

void handleChildAndParentRef(const Parent& p, const Child& c) {
	auto cp = c.father.lock();
	auto pc = p.son.lock();
	if (cp.get() == &p && pc.get() == &c) {
		std::cout << "right relation\n";
	}
	else {
		std::cout << "oop!!!!!\n";
	}
}

void handleChildAndParent(const ParentPtr& p, const ChildPtr& c) {
	auto cp = c->father.lock();
	auto pc = p->son.lock();
	if (cp == p && pc == c) {
		std::cout << "right relation\n";
	}
	else {
		std::cout << "oop!!!!!\n";
	}
}

Child::Child() { std::cout << "hello child\n"; }
Parent::Parent() { std::cout << "hello parent\n"; }
Child::~Child() { std::cout << "bye child\n"; }
Parent::~Parent() { std::cout << "bye parent\n"; }

void Parent::checkRelation() {
	auto ps = son.lock();
	if (ps) {
		// this
		handleChildAndParent(shared_from_this(), ps);
	}
	std::cout << "after call checkRelation\n";
}

void Child::checkRelation() {
	// we call handleChildAndParent
}

void testParentAndChild() {
	Parent pp;
	ParentPtr p(new Parent());
	ChildPtr c(new Child());
	p->son = c; // c.use_count() == 2 and p.use_count() == 1
	c->father = p; // c.use_count() == 2 p.use_count() == 2
	p->checkRelation();
}

int main() {
	testParentAndChild();
}

4、shared_ptr,weak_ptr和裸指针相比会大很多,并且效率上会有影响,尤其是在多线程模式下。

关于这点自己实现一个智能指针就知道了。

一个shared_ptr在空间上至少是三个裸指针的大小(24个字节),本身有引用还要配合weak_ptr使用所以要保存多少该指针的引用。如下生成既有对象的new还有本身的new:

代码语言:javascript
复制
ObjectPtr obj3(new Object(2));

ObjectPtr obj4 = obj3进行拷贝时时间效率会慢很多 可以用以下方式减少空间

代码语言:javascript
复制
ObjectPtr obj5 = std::make_shared<Object>(3);
//ObjectPtr obj5(new Object(3));

5、如果有可能,优先使用类的实例,其次万不得已使用std::unique_ptr,再万不得已使用std:shared_ptr。

用unique_ptr和用shared_ptr一样为了防止处理某些异常时无法调用delete释放资源的情况,在同一个特定的时刻只会有一个unique_ptr来管理一份资源没有共享模式,所以拷贝构造函数,=符号拷贝操作等是不存在的。

由于unique_ptr的唯一性所以要转移资源可以transfer传值,只能调用obj的右值引用而不能用左值,transfer函数执行完就释放了,调用了transfer后原有的会变成空指针不再管理。

代码语言:javascript
复制
#include <cassert>
#include <memory>
#include <iostream>

typedef int Object;

typedef std::unique_ptr<Object> UniqueObjectPtr;
typedef std::shared_ptr<Object> SharedObjectPtr;

void print(const UniqueObjectPtr& obj) {}

void transfer(UniqueObjectPtr obj) {
	std::cout << obj << std::endl;
}

void uniquePtr() {
	UniqueObjectPtr obj(new Object(1));
	auto p = obj.get(); // operator bool
	if (p) {
		std::cout << p << std::endl;
	}
	// better
	if (obj) {
		std::cout << obj << std::endl;
	}

	// operator -> *
	std::cout << p << obj << std::endl;

	p = obj.release();
	delete p;

	obj.reset();
	obj.reset(new Object(2)); // obj.reset();
	// UniqueObjectPtr(const UniqueObjectPtr&) = delete
	// UniqueObjectPtr(UniqueObjectPtr&&) = default
	transfer(std::move(obj));

	assert(obj == nullptr);
	//std::cout << obj->id() << std::endl;

	obj.reset(new Object(4));
	SharedObjectPtr sharedObj(std::move(obj));
	assert(obj == nullptr);
	// shared_ptr weak_ptr enable_shared_from_this
	// unique_ptr
}

6、智能指针只能表示所有权,如果遇到某些复杂的数据结构,或者所有权不明确的场景,还是得裸指针来。 也很好举例,用智能指针写个二叉树试试。

好了就说到这儿吧,再说多了怕是以后都不敢用了。 今天之所以要写这么一篇,是最近看智能指针的好处被吹的天花乱坠的让我都有点想把以前裸指针的代码全改成智能指针了。 但是呢,不要忘了我们开头的那句话哦。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-10-18 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档