C++11 enable_shared_from_this<>与shared_from_this()

智能指针的有关函数使用注意

    • 智能指针分类
    • shared_from_this()函数
    • demo测试是否真正理解


智能指针分类

  1. unique_ptr
    unique_ptr是个独占指针,C++ 11之前就已经存在,unique_ptr所指的内存为自己独有,某个时刻只能有一个unique_ptr指向一个给定的对象,不支持拷贝和赋值。
#include 
#include 
#include 
#include 
#include 


void test()
{
    std::unique_ptr<int> up1(new int(11));   // 无法复制的unique_ptr
    // unique_ptr up2 = up1;        // err, 不能通过编译
    std::cout << *up1 << std::endl;   // 11

    std::unique_ptr<int> up3 = std::move(up1);    // 现在p3是数据的唯一的unique_ptr

    std::cout << *up3 << std::endl;   // 11
    // std::cout << *up1 << std::endl;   // err, 运行时错误,空指针
    up3.reset();            // 显式释放内存
    up1.reset();            // 不会导致运行时错误
    // std::cout << *up3 << std::endl;   // err, 运行时错误,空指针

    std::unique_ptr<int> up4(new int(22));   // 无法复制的unique_ptr
    up4.reset(new int(44));  // "绑定"动态对象
    std::cout << *up4 << std::endl; // 44

    up4 = nullptr; // 显式销毁所指对象,同时智能指针变为空指针。与up4.reset()等价

    std::unique_ptr<int> up5(new int(55));
    int *p = up5.release(); // 只是释放控制权,不会释放内存
    std::cout << *p << std::endl;
    // cout << *up5 << endl; // err, 运行时错误,不再拥有内存
    delete p; // 释放堆区资源

    return;
}

  1. shared_ptr
    shared_ptr允许多个该智能指针共享“拥有”同一堆分配对象的内存,这通过引用计数(reference counting)实现,会记录有多少个shared_ptr共同指向一个对象,一旦最后一个这样的指针被销毁,也就是一旦某个对象的引用计数变为0,这个对象会被自动删除。支持复制和赋值操作。
#include 
#include 
#include 
#include 
#include 


void test()
{
    std::shared_ptr<int> sp1(new int(22));
    std::shared_ptr<int> sp2 = sp1;
    std::cout << "cout: " << sp2.use_count() << std::endl; // 打印引用计数, 2

    std::cout << *sp1 << std::endl;  // 22
    std::cout << *sp2 << std::endl;  // 22

    sp1.reset(); // 显示让引用计数减一
    std::cout << "count: " << sp2.use_count() << std::endl; // 打印引用计数, 1

    std::cout << *sp2 << std::endl; // 22

    return;
}

  1. weak_ptr
    weak_ptr是为配合shared_ptr而引入的一种智能指针来协助shared_ptr工作,它可以从一个shared_ptr或另一个weak_ptr对象构造,它的构造和析构不会引起引用计数的增加或减少。没有重载 *和 -> 但可以使用lock获得一个可用的shared_ptr对象。
    weak_ptr的使用更为复杂一点,它可以指向shared_ptr指针指向的对象内存,却并不拥有该内存,而使用weak_ptr成员lock,则可返回其指向内存的一个share_ptr对象,且在所指对象内存已经无效时,返回指针空值nullptr。

weak_ptr并不拥有资源的所有权,所以不能直接使用资源。 可以从一个weak_ptr构造一个shared_ptr以取得共享资源的所有权。
weak_ptr解决shared_ptr循环引用的问题

class CB;
class CA
{
public:
    CA() { cout << "CA() called! " << endl; }
    ~CA() { cout << "~CA() called! " << endl; }
    void set_ptr(shared_ptr<CB>& ptr) { m_ptr_b = ptr; }
    void b_use_count() { cout << "b use count : " << m_ptr_b.use_count() << endl; }
    void show() { cout << "this is class CA!" << endl; }
private:
    shared_ptr<CB> m_ptr_b;
};

class CB
{
public:
    CB() { cout << "CB() called! " << endl; }
    ~CB() { cout << "~CB() called! " << endl; }
    void set_ptr(shared_ptr<CA>& ptr) { m_ptr_a = ptr; }
    void a_use_count() { cout << "a use count : " << m_ptr_a.use_count() << endl; }
    void show() { cout << "this is class CB!" << endl; }
private:
    shared_ptr<CA> m_ptr_a;
};

void test_refer_to_each_other()
{
    shared_ptr<CA> ptr_a(new CA());
    shared_ptr<CB> ptr_b(new CB());

    cout << "a use count : " << ptr_a.use_count() << endl;
    cout << "b use count : " << ptr_b.use_count() << endl;

    ptr_a->set_ptr(ptr_b);
    ptr_b->set_ptr(ptr_a);

    cout << "a use count : " << ptr_a.use_count() << endl;
    cout << "b use count : " << ptr_b.use_count() << endl;
}

// 测试结果
CA() called!
CB() called!
a use count : 1
b use count : 1
a use count : 2
b use count : 2


shared_from_this()函数

c++11中的shared_from_this()来源于boost中的enable_shared_form_this类和shared_from_this()函数,功能为返回一个当前类的std::share_ptr。

当类A被share_ptr管理,且在类A的成员函数里需要把当前类对象作为参数传给其他函数时,就需要传递一个指向自身的share_ptr。

我们就使类A继承enable_share_from_this,然后通过其成员函数share_from_this()返回当指向自身的share_ptr。

class A : public enable_shared_from_this<A> {
public:
	weak_ptr<A> Func() {
		return shared_from_this();
	}
};
  • 把当前类对象作为参数传给其他函数时,为什么要传递share_ptr呢?直接传递this指针不可以吗?
    一个裸指针传递给调用者,谁也不知道调用者会干什么?假如调用者delete了该对象,而share_tr此时还指向该对象。

  • 这样传递share_ptr可以吗?share_ptr
    这样会造成2个非共享的share_ptr指向一个对象,最后造成2次析构该对象

//错误示例,最后会报错
#include 
#include 
 
class Bad
{
public:
	std::shared_ptr<Bad> getptr() {
		return std::shared_ptr<Bad>(this);
	}
	~Bad() { std::cout << "Bad::~Bad() called" << std::endl; }
};
 
int main()
{
	// 错误的示例,每个shared_ptr都认为自己是对象仅有的所有者
	std::shared_ptr<Bad> bp1(new Bad());
	std::shared_ptr<Bad> bp2 = bp1->getptr();
	// 打印bp1和bp2的引用计数
	std::cout << "bp1.use_count() = " << bp1.use_count() << std::endl;
	std::cout << "bp2.use_count() = " << bp2.use_count() << std::endl;
}  // Bad 对象将会被删除两次
//正确示例
#include 
#include 
 
struct Good : std::enable_shared_from_this<Good> // 注意:继承
{
public:
	std::shared_ptr<Good> getptr() {
		return shared_from_this();
	}
	~Good() { std::cout << "Good::~Good() called" << std::endl; }
};
 
int main()
{
	// 大括号用于限制作用域,这样智能指针就能在system("pause")之前析构
	{
		std::shared_ptr<Good> gp1(new Good());
		std::shared_ptr<Good> gp2 = gp1->getptr();
		// 打印gp1和gp2的引用计数
		std::cout << "gp1.use_count() = " << gp1.use_count() << std::endl;
		std::cout << "gp2.use_count() = " << gp2.use_count() << std::endl;
	}
	system("pause");
} 

demo测试是否真正理解

#include
using namespace std;

class A : public enable_shared_from_this<A> {
public:
	weak_ptr<A> Func() {
		return shared_from_this();
	}
};

int main() {
	auto a = make_shared<A>();//1对
	//unique_ptr a(new A);//2错
	//A* a = new A;//3错
	//auto a = make_unique();//4错
	//shared_ptr a(new A);//5对
	a->Func();
	return 0;
}

这里面只有1和5是可以运行的

原因:调用shared_from_this()函数,必须要求对象是一个被智能指针shared_ptr管理的对象。

你可能感兴趣的:(C++语法,c++,指针,内存管理)