结合作业总结智能指针share_ptr知识点

智能指针share_ptr知识点

1、原理

智能指针share_ptr 的原理简单来说,就是**做引用计数,多一个引用就加1,少一个引用,就减去1,当引用计数为0,则认为没有人用了,就主动调用delete,完成对象释放。**

2、关键变量

要实现智能指针,其关键变量为:
a) 指向托管对象的指针 T* m_ptrRef;
b) 引用计数变量的指针,即一个int指针 int m_count;

3、关键函数

//(a) 重载运算符=  ->

//赋值运算符重载 =		
template<typename T>
MySharedPtr<T>& MySharedPtr<T>::operator = (const MySharedPtr<T>& sp)
{
	//若计数器为空,删除指针
	if (m_ptrRef != nullptr)
	{
		release();
	}
	cout << "\t引用计数:" << sp.m_ptrRef->m_count << endl;
	m_ptrRef = sp.m_ptrRef;
	sp.m_ptrRef->m_count++;
	return *this;
}


//重载运算符 ->		m_ptrRef指向什么,本模板类也指向什么
template<typename T>
T* MySharedPtr<T>::operator->()
{
	cout << "\t引用计数:" << m_ptrRef->m_count << endl;
	return m_ptrRef->m_ptrRef;
}
//(b) 构造函数写两个,一个是参数为托管对象的指针,一个是参数为智能指针本身

// 初始化模板类对象,把托管对象的指针T带进来
template<typename T>
MySharedPtr<T>::MySharedPtr(T* ptr) :m_ptrRef(new PtrRefCountHelper<T>(ptr))
{
	cout << "MySharedPtr()默认构造" << endl;
}

//参数为智能指针本身
template<typename T>
MySharedPtr<T>::MySharedPtr(const MySharedPtr<T>& sp)
{
	cout << "\t引用计数:" << sp.m_ptrRef->m_count << endl;
	//m_ptrRef浅拷贝给sp
	m_ptrRef = sp.m_ptrRef;
	//指针引用调用一次 m_count+1
	sp.m_ptrRef->m_count++;
	cout << "MySharedPtr()拷贝构造" << endl;
}
//(c) 引用计数加  函数主体
m_ptrRef = sp.m_ptrRef;
sp.m_ptrRef->m_count++;
//(d) 引用计数减release()函数,以及减到0时释放托管对象
//计数值--
template<typename T>
void MySharedPtr<T>::release()
{
	cout << "\t引用计数:" << m_ptrRef->m_count << endl;
	//析构一次执行一次 m_ptrRef->m_count-1	--在前,先-1再判定,
	//当m_ptrRef->m_count == 0,释放指针对象
	if (--m_ptrRef->m_count == 0)
	{
		delete m_ptrRef;
	}
}

4、weak_ptr

环的问题:调用构造却不调用析构,造成内存泄露。

解决办法:使用 weak_ptr

weak_ptr 可以包含由 shared_ptr 管理的内存的引用,但 weak_ptr 不拥有这个内存,所以不能阻止 shared_ptr 释放内存。weak_ptr 离开作用域的时候不会销毁它指向的内存。

weak_ptr 的构造函数需要将一个 shared_ptr 或另一个 weak_ptr 作为参数。为了访问 weak_ptr 中保存的指针,需要将 weak_ptr 转换为 shared_ptr。这有两种方法:

使用 weak_ptr 实例的 lock() 方法,这个方法返回一个 shared_ptr
weak_ptr 作为 shared_ptr 构造函数的参数,创建一个新的 shared_ptr 实例。
这两种情况下,如果 weak_ptr 关联的 shared_ptr 已经释放,新 shared_ptr 就是 nullptr

#include <iostream>
#include <memory>
std::weak_ptr<int> gw;
void f()
{
    if (auto spt = gw.lock()) { // 使用之前必须复制到 shared_ptr
        std::cout << *spt << "\n";
    }
    else {
        std::cout << "gw is expired\n";
    }
}
int main()
{
    {
        auto sp = std::make_shared<int>(42);
        gw = sp;
        f();
    }
    f();
}

5、小结

简单地讲,要想尽量减少管理内存的痛苦,那就尽量使用智能指针,消灭 new,没有 new 就没有 delete,没有 malloc() 就没有 free()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智能指针share_ptrC++11标准库中的一种用于管理动态分配内存的智能指针。它能够自动管理资源,在不需要时释放内存,防止内存泄漏。然而,在实际代码中,我们常常会遇到相互引用的情况,即两个或多个对象之间产生循环引用,导致内存泄漏。这种情况对于传统的裸指针来说是无法解决的,但对于智能指针share_ptr来说,则可以通过以下方法解决: 1.使用weak_ptr:在循环引用的情况下,一个对象可以通过weak_ptr来共享相应的资源,而不会增加资源的引用计数。因此,在处理相互引用问题时,可以使用weak_ptr来打破循环引用,避免内存泄漏。 2.使用单独的管理对象:在某些情况下,多个对象之间的相互引用较为复杂,使用weak_ptr不能完全解决问题,例如多层嵌套的相互引用。这时候,可以引入一个额外的管理对象,用于管理这些对象之间的关系,从而减少相互引用的复杂度。 3.使用裸指针代替智能指针:虽然智能指针share_ptr可以很好地管理内存,但在某些场景下,使用裸指针可能会更为简单、清晰。例如,在处理循环引用时,可以使用裸指针进行判断,然后手动删除内存。 综上所述,智能指针share_ptrC++中非常有用的工具,在避免内存泄漏方面发挥了很大的作用。虽然在处理相互引用时可能会遇到一些麻烦,但使用上述方法可以很好地解决问题,保证代码质量和性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值