类的内部需要调用自己的智能指针时this智能指针难以传入,出了作用域会调用析构

所以伪造一个智能指针来传this是错误的,他会管理同样一份资源调用两次析构

需要把自己作为智能指针传入,调用的时候应该用奇异模板递归(CRTP)

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

以下是完整代码:

#include <cassert>
#include <memory>
#include <iostream>
// auto_ptr
// shared_ptr
// enable_shared_from_this // CRTP
// weak_ptr
// unique_ptr
void sharedPtrNotice();
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();
}


static void interfaceOfSharedPtr();
static void sharedPtrWithWeakPtr();
static void uniquePtr();
int main() {
	testParentAndChild();
//	interfaceOfSharedPtr();
//	sharedPtrWithWeakPtr();
//	uniquePtr();
}
Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐