我们知道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();
}
嗯,现在,就说这么多吧!强引用和弱引用以及循环引用等概念还不是很熟。后面少玩游戏,多学习!要学的还是比较多的!