C++智能指针

1、智能指针的概念

(1)指针及其存在的问题

        指针是一个变量,它的值为另一个变量的地址。使用指针可以很灵活地操纵数据对象,但是指针使用不当会造成内存泄漏指向的内存出错野指针等问题使程序崩溃。

(2)智能指针的引入

        我们先看下面这段代码:

void RemoveAt(vector<char*> &v, int i)
{
	if(i < v.size())
		v.erase(v.begin() + i);
}

        在执行vector删除元素时,并没有释放指针所指向的空间,就引起了内存泄漏,这是大家常犯的错误。而如何避免这个问题?我们可能会说,我在删除元素前delete掉当前指针不就行了?是的,你现在这么想,其他人可不会时常记得,如果你要对一个庞大的工程进行检查,看是否有这种潜在的内存泄露问题,那会是一场灾难!

        我们知道,面向对象编程中,一个类包含了构造函数和析构函数,在构造函数中,我们可以对类中成员变量进行内存分配,而在析构函数中,我们可以对类中成员变量进行内存回收。

        C++正是将类的析构思想应用到了指针中,因此,C++引入了智能指针的概念,智能指针是一个类类型对象,在其内部封装了一个普通指针。当智能指针对象因离开作用域而被析构时,其析构函数被执行,通过其内部封装的普通指针,销毁该指针的目标对象,避免内存泄露。

2、智能指针的使用

  • STL一共给我们提供了四种智能指针:auto_ptr、unique_ptr、shared_ptr和weak_ptr。
  • 所在头文件:#include<memory>
        注:模板auto_ptr是C++98提供的解决方案,C+11已将将其摒弃,并提供了另外两种解决方案(unique_ptr和shared_ptr)。然而,虽然auto_ptr被摒弃,但它已使用了好多年,所以现在依旧保存。
  • 用法举例:
    #include <memory>
    #include <iostream>
    using namespace std;
    
    class A
    {
    public:
    	void fun()
    	{
    		cout << "A::fun()" << endl;
    	}
    	~A()
    	{
    		cout << "~A has been called" << endl;
    	}
    };
    
    int main()
    {
    	{
    		std::auto_ptr<A> sp(new A); //创建智能指针
    		sp->fun(); //引用智能指针的内容
    		sp.reset(new A); //给智能指针重新赋值,原来的指针将被析构
    		A a = *sp; //获取智能指针指向的内容
    	}//离开作用域后,智能指针析构
    
    	{
    		std::unique_ptr<A> sp(new A);
    		sp->fun();
    	}
    	{
    		std::shared_ptr<A> sp(new A);
    		sp->fun();
    	}
    	{
    		std::shared_ptr<A> sp1(new A);
    		std::shared_ptr<A> sp2 = sp1;
    		std::weak_ptr<A> wp(sp2); //观测sp2所指向内容
    		cout << wp.expired() << endl; //观测智能指针是否已经失效 False
    		cout << wp.use_count() << endl; //观测智能指针的引用计数 2
    	}
    
    	system("pause");
    	return 0;
    }

3、auto_ptr、unique_ptr、shared_ptr、weak_ptr的用法与区别

        当两个智能指针指向同一个对象时,如以下代码块,在其结束后,程序将试图删除同一个对象两次(一次是sp1过期时,另一次是sp2过期时)。这就出现了问题,为了避免这种问题,auto_ptr、unique_ptr、shared_ptr分别采取了不同的方式:

{
	std::auto_ptr<A> sp1(new A);
	std::auto_ptr<A> sp2 = sp1;
}

(1)auto_ptr和unique_ptr

        对于特定的对象,只能有一个智能指针可拥有,这样只有拥有对象的智能指针的构造函数会删除该对象。然后让赋值操作转让所有权。

        auto_ptr和unique_ptr的区别是,在执行sp2 = sp1这条语句时,auto_ptr方式将会让sp2剥夺sp1的所有权,并且在以后的代码中继续访问sp1将会出错,因此auto_ptr是不安全的,这也是它被摒弃的原因。而unique_ptr会在编译的时候提示这条语句非法,所以unique_ptr更安全,并且,当程序试图将一个 unique_ptr 赋值给另一个时,如果源 unique_ptr 是个临时右值,编译器允许这么做;如果源 unique_ptr 将存在一段时间,编译器将禁止这么做。

(2)shared_ptr

        对于特定的对象,可以由多个智能指针拥有,但需要创建智能更高的指针,跟踪引用特定对象的智能指针数。这称为引用计数。例如,赋值时,计数将加1,而指针过期时,计数将减1,当减为0时才调用delete。

(3)weak_ptr

        weak_ptr是为了配合shared_ptr而引入的一种智能指针,因为它不具有普通指针的行为,没有重载operator*和->,它的最大作用在于协助shared_ptr工作,像旁观者那样观测资源的使用情况。weak_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。

比较详细的文章参考:https://www.cnblogs.com/lanxuezaipiao/p/4132096.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值