浅析智能指针

我们知道c和c++相对于其他编程语言是相当自由的语言,给了用户很大的权限,比较信任用户!它允许用户自由分配计算机内存,然后用户需手动释放,但是这就带来了一定的风险,要知道内存要是申请了不手动释放,这块内存就不会作为空闲空间来供以后使用,可想而知,编写程序要是申请的内存太多(当然现在编译器都是比较智能的,有一定的内存保护机制),不释放,就可能导致主机可用空间不足,最终结果就是死机重启!!!
作为向c语言自身来说,就有一些缺陷,现在我们看一个例子:

A:
int * getspace(){
	static int a[100] ; 
	return a ;
}
B:
int * getspace(){
	int *a = malloc(100);
	return a ;
}

这两个函数的功能都是相同的都是返回一个长度为100的int数组,但相信大家都会发现一个问题,A函数是不需要手动释放内存的,因为static变量的生命周期和程序的生命周期是一样的,而B函数它malloc的内存必须通过free 释放掉,而函数就是对外开放的接口,用户只需要学会用他能实现的功能就行,不需理解它内部实现,这就是非常危险的!!!要是设计一个应用程序函数都像B函数那样写,那就凉了!
还有在c++中,当我们在new 一个对象时,在最后,必须调用delete释放,但是这样真的能解决问题吗???肯定不能呀!

#include<iostream>
#include<stdlib.h>
using namespace std;
class A{
private:
	int a ;
public:
	A(){}
	~A(){}
};
int main(){
	
	A * s = new A();
	while(1){
		cout<<"好好学习,远离王者"<<endl;
	}
	delete s ;
}

比如说上面一个简单的程序,执行时,在循环除它就不会退出了,然后我们执行强制退出,那程序是不会执到delete那块的,所以就内存泄漏了!
所以,总的来说,无论是new和delete还是malloc 和free都不是保险可行的内存保护策略!
所以在c++中就有了专门防止内存泄漏的方法,在c++98之前,用的是auto_ptr,但随着c++的发展,这种保护方法被开发者逐渐弃用,我今天要说的是另外三种现在比较通用的新的c++智能指针方法,是c++11新特性。
shared_ptr //可以实现相同类型指针之间的相互赋值!
unique_ptr //对于某一对象特有的指针,不能实现指针之间的相互赋值!
weak_ptr //通常和shared_ptr 一起使用,是shared_ptr 的一种弱引用(非拥有:当引用的对象活着的时候不一定存在。仅仅是当它自身存在的时的一个引用),在使用时转换成shared_ptr。
三种方法都包含在memory.h头文件中其用法示例如下:

#include<iostream>
#include<memory>
#include<mcheck.h>
using namespace std;
class A{
public:
	A()	{
		a++ ;
		cout<<"build"<<"  "<<a<<endl;}
	~A(){
		a-- ;
		cout<<"destroy"<<"  "<<a<<endl;
	}
    void say(){
        cout<<"away from kingdom game"<<endl ;
    }
private:
	static int a ;
};

int A::a = 0 ;
int main(){
//检验是否内存泄漏 
    mtrace();
	shared_ptr<A>demo1(new A);
	shared_ptr<A>demo2(new A);
	weak_ptr <A>demo3 = demo1;
    demo1->say();
    demo2->say();
    auto s= demo3.lock();
    demo1->say();
    s->say();
 }

运行过程截图:
在这里插入图片描述

可以发现,用上智能指针,并没有造成内存泄露问题。智能指针用的时候就和普通指针的用法差不多。它内部实现重载了*和->运算符。
以上程序中weak_ptr作为shared_ptr的引用,在使用时需要转化为shared_ptr。
还有unique_ptr的用法,和shared_ptr差不多,但是不能实现像指针那样互相赋值的操作,它是一个对象特有的指针,其他unique_ptr类型的指针不能再指向该对象。用法如下:

#include<stdio.h>
#include<iostream>
#include<memory>
using namespace  std;
class A{

private: 
    static int a ;
public:

    A(){
        a++ ;
        cout<<"the demo built"<<a<<endl ;
    }
    ~A(){
        a-- ;
        cout<<"the demo destroy"<<a<<endl ;
    }
    void say(){
        cout<<"demo"<<endl;
    }
};
int A::a = 0;
int main(){

    cout<<"-------------------unique ptr----------------"<<endl ;
    unique_ptr <A>demoa(new A);
    unique_ptr <A>demob(new A);
    //这一步是错误的,不能互相赋值。
    // unique_ptr democ = demob;
    demoa->say();
    demob->say();
}

嗯,现在,就说这么多吧!强引用和弱引用以及循环引用等概念还不是很熟。后面少玩游戏,多学习!要学的还是比较多的!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值