effective c++ 08 以对象管理资源02

本文深入探讨了C++11中引入的智能指针概念,包括shared_ptr和unique_ptr的使用,展示了如何利用它们有效管理资源,防止内存泄漏,特别强调了引用计数和所有权转移的机制。

以对象管理资源02

请记住:任何技术都是一层窗户纸,一捅就破。只是起了一个牛逼的名字而已,我们花老爷grape告诉我,再怎么花哨的技术,无非就是封装、继承、多态而已。话不多说开始本节的重点智能指针(以对象管理资源)。
自C++11起,C++标准提供两大类型的智能指针:
  1. Class shared_ptr实现共享式拥有(shared ownership)概念。多个智能指针可以指向相同对象,该对象和其相关资源会在“最后一个引用(reference)被销毁”时候释放。为了在结构复杂的情境中执行上述工作,标准库提供了weak_ptr、bad_weak_ptr和enable_shared_from_this等辅助类,但我们一般用的weak_ptr比较多
  2. Class unique_ptr实现独占式拥有(exclusive ownership)或严格拥有(strict ownership)概念,保证同一时间内只有一个智能指针可以指向该对象。它对于避免资源泄露(resourece leak)——例如“以new创建对象后因为发生异常而忘记调用delete”——特别有用。

一.shared_ptr的使用
shared_ptr多个指针指向相同的对象。shared_ptr使用引用计数,每一个shared_ptr的拷贝都指向相同的内存。每使用他一次,内部的引用计数加1,每析构一次,内部的引用计数减1,减为0时,自动删除所指向的堆内存。shared_ptr内部的引用计数是线程安全的,但是对象的读取需要加锁。
1. 智能指针是个模板类,可以指定类型,传入指针通过构造函数初始化。也可以使用make_shared函数初始化。不能将指针直接赋值给一个智能指针,一个是类,一个是指针。例如std::shared_ptr pp = new int(10);的写法是错误的.
2. get函数可以获取原始指针
3. 请不要用一个原始指针初始化多个shared_ptr,否则会造成二次释放同一内存,导致出错。
看看下面的例子:

#include <iostream>
#include <memory>
int main() {
    {
        int a = 10;
        std::shared_ptr<int> ptra = std::make_shared<int>(a);
        std::shared_ptr<int> ptra2(ptra); //copy
        std::cout << ptra.use_count() << std::endl;//2

        int b = 20;
        int *pb = &a;
        //std::shared_ptr<int> ptrb = pb;  //error
        std::shared_ptr<int> ptrb = std::make_shared<int>(b);//1
        ptra2 = ptrb; //assign
        pb = ptrb.get(); //获取原始指针

        std::cout << ptra.use_count() << std::endl;//1
        std::cout << ptrb.use_count() << std::endl;//2
    }
}

结果:
在这里插入图片描述
请继续看:

class  A1
{
public:
	A1(int x,int y)
	{
		a = x;
		b = y;

	}
	void show()
	{
		cout << a << " " << b << endl;
	}
	int a, b;
	~A1()
	{
		cout << "~A1\n";
	}
};

void gogo()
{
	//类
	shared_ptr<A1>m_pp = make_shared<A1>(1, 2);
	m_pp->show();
	A1 *m_ap1 = new A1(100,200);
	shared_ptr<A1>m_spap1(m_ap1);
	m_spap1->show();
	//普通类型
	shared_ptr<int>m_pt = make_shared<int>(10);
	cout << *m_pt << endl;

	//int a = 20;
	//shared_ptr<int> m_myp(&a);//注意这样是不行的因为变量a在栈区。

	int *pa = new int(1000);
	shared_ptr<int> m_spa(pa);
	cout << *pa << endl;
	
}
int main() {
		
	
	gogo();
	
	system("pause");
}

结果:
在这里插入图片描述
二.unique_ptr的使用
 unique_ptr“唯一”拥有其所指对象,同一时刻只能有一个unique_ptr指向给定对象(通过禁止拷贝语义、只有移动语义来实现)。相比与原始指针unique_ptr用于其RAII的特性,使得在出现异常的情况下,动态资源能得到释放。unique_ptr指针本身的生命周期:从unique_ptr指针创建时开始,直到离开作用域。离开作用域时,若其指向对象,则将其所指对象销毁(默认使用delete操作符,用户可指定其他操作)。unique_ptr指针与其所指对象的关系:在智能指针生命周期内,可以改变智能指针所指对象,如创建智能指针时通过构造函数指定、通过reset方法重新指定、通过release方法释放所有权、通过移动语义转移所有权。

#include <iostream>
#include <memory>

int main() {
    {
        std::unique_ptr<int> uptr(new int(10));  
        //std::unique_ptr<int> uptr2 = uptr;  //不能赋值
        //std::unique_ptr<int> uptr2(uptr);  //不能复制
        std::unique_ptr<int> uptr2 = std::move(uptr); //装换所有权
        uptr2.release(); //释放所有权
    }
    }

继续看代码:

void gogog1()
{
	unique_ptr<A1>m_pp(new A1(1, 2));
	m_pp->show();
	m_pp.release();//转换之后m_pp为空
	m_pp->show();//会报错
}

当指针m_pp离开作用域后就会释放指针所指内存。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

发如雪-ty

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值