C++11:智能指针

智能指针:是指用于存储和封装指针的类,被存储的指针指向了从堆上动态分配的对象,能够在适当的时间自动删除指向的对象。智能指针在面对异常的时候能确保正确的销毁动态分配的对象。也可以用于跟踪被多用户共享的动态分配对象 使用operator-> 和 operator* 来生成原始指针,看上去就像一个普通指针

auto_ptr<T> ptr(new T);
*ptr
ptr->value   不用手动delete

实现一个最简单的智能指针:

template<typename T>
class MyPtr {
public:
	MyPtr(T* ptr = nullptr) :rawptr(ptr) {
	}
	MyPtr(const MyPtr<T>& rh) {
		rawptr = rh.rawptr;
		rh.rawptr == nullptr;
	}
	~MyPtr() {
		delete rawptr;
	}
	T& operator*()const {
		return *rawptr;
	}
	T* operator->()const {
		return rawptr;
	}
	bool operator!()const {
		return rawptr == nullptr;
	}
	MyPtr<T>& operator=(MyPtr<T>& rh) {
		if (rh != this) {
			delete rawptr;
			rawptr = rh.rawptr;
			rh.rawptr == nullptr;
		}
		return *this;
	}
private:
	T* rawptr;
};

早起智能指针的不足:

在早期的C++编程领域里,智能指针的实现:auto_ptr 是已经存在了的
auto_ptr 存在下面一些问题:

  1. auto_ptr不能共享所有权。一旦智能指针被拷贝或者赋值比如

    auto_ptr<type>p1(new type);
    auto_ptr<type>p2 = p1;//拷贝
    auto_ptr<type>p3;
    p3 = p1;//赋值

    这样会导致p2 p3 p1同时指向p1内部的原始指针,由于每一个auto_ptr在被销毁的时候都会删除其所指向的对象,原始指针就会被重复删除3次,为了解决这个问题,要么禁用拷贝与赋值运算符,要么设计当auto_ptr拷贝或者赋值的时候对原始指针的所有权转移到新对象去

  2. auto_ptr不能指向数组

  3. auto_ptr不能作为容器成员

  4. auto_ptr不能通过赋值操作来初始化
    std::auto_ptr<int> p = new int(42)//错
    std::auto_ptr<int> p new int(42)//对

C++11中的三大智能指针

unique_ptr

unique_ptr可以看成是auto_ptr的替代品,用法

  1. 不支持拷贝构造和赋值运算函数
    unique_ptr<Obj>ap(new Obj);
    unique_ptr one(ap);//会出错
    unique_ptr two= one;//会出错
    unique_otr对对象引用比较专一,不允许随便转移
  2. 可以移动构造和移动赋值操作
    unique_ptr<Obj> Getobj();
    {
         unique_ptr<Obj>ptr(new Obj);
         return ptr;
    }
    unique<Obj>ptr = Getobj;

    unique_ptr<Obj>ptr1(new Obj());
    unique_ptr<Obj>ptr2(std::move(ptr1));

shared_ptr

如果程序要使用多个指向同一个对象的指针,那么可以使用shared_ptr
基本使用方法:

shared_ptr <int> p1(new int (5));
shared_ptr<int> p2 = make_shared<int>(10);

int * pint = new int(10);

//shared_ptr<int>p3 = pint; //error
//p3 = pint;//error

use_count() //计数数量

unique() //是否只被一个使用

注意事项

纯指针不能给智能指针复制或者拷贝构造

shared_ptr多次引用同一数据,会导致两次释放同一内存

循环引用:
        程序退出前,node1的引用计数为2,node2的引用计数也为2,退出时,shared_ptr所做操作就是简单的将计数减1,如果为0则释放,显然,这个情况下,引用计数不为0,于是造成node1和node2内存得不到释放,就造成了内存泄漏

多线程安全问题(引用计数的修改)

weak_ptr

shared_ptr 是一种强引用关系,智能指针直接引用对象,代码会引起循环引用,从而造成内存泄漏

weak_ptr 用于配合shared_ptr使用 并不影响对象的生命周期,即存在与否并不影响对象的引用计数器,weak_ptr并没有重载operator-> 和operator* 操作符,因此不可直接通过weak_ptr使用对象。提供了expired() 与 lock() 成员函数前者用于判断weak_ptr指向的对象是否已被销毁,后者返回其所指对象shared_ptr智能指针(对象销毁时,返回空shared_ptr)

weak_ptr被设计为shared_ptr 共同工作,可以从一个shared_ptr或者另一个weak_ptr对象构造,获得资源观测权,但weak_ptr没有共享资源,它的构造不会引起指针引用计数的增加

使用weak_ptr的use_count()可以观测资源的引用计数,另一个成员函数expired()的功能等价use_count()==0 但更快,表示被观测资源(也就是shared_ptr管理的资源)已经不复存在

weak_ptr可以使用一个非常重要的成员函数lock()从被观测的shared_ptr获得一个可用的shared_ptr对象,从而操作资源,但当expired==true的时候,lock()函数将返回一个存储空指针的shared_ptr

shared_ptr<int> spi1(new int(100));
shared_ptr<int> spi2(spi1);
weak_ptr<int> wp1 = spi1;// 观察spi1,不增加引用计数
cout<<wp1.use_count()<<endl;//观察    不能使用*   ->
cout<<wp1.expired() << endl; 观察, 不能使用 *  ->
auto spi1 = wp1.lock();
if(spi)
{
cout<<*spi<<endl;
}

就是观察,资源有没有被引用 有没有被释放

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

#A#

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

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

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

打赏作者

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

抵扣说明:

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

余额充值