为什么要使用智能指针?
在我们使用指针的时候,在分配了内存之后我们有时会忘记了释放内存,但造成内存泄漏对于一个程序员来讲简直是一个巨大的噩耗.泄漏一点点内存是没啥影响,但如果是在一个循环中不断的消耗内存呢?当内存消耗完了之后就会宕机,这是我们一定要杜绝发生的,那怎么样才能避免此类的事情发生呢?
比如下面的代码就很容易造成内存泄漏,我们以为代码会朝着我们理想的方向走,不会发生文件打不开的情况,此时我们又需要在里面抛出一个异常的时候,这就造成了内存泄漏就悲剧了~!
//分配内存
int newMemory() {
ifstream ostream;
string* str = new string("内存泄漏很危险,要小心啊~");
ostream.open("data.txt");
if (!ostream.is_open()) {
//to do....
{
throw exception("文件不存在");
}
}
cout << *str << endl;
delete str;//释放内存
return 0;
}
为避免此类事情的发生,C++一众大牛们推出了"智能指针"这一概念,下面我就介绍一下智能指针:
1.auto_ptr.
auto_ptr 是C++98 定义的一个智能指针模板,他为我们提供了更为有效的对指针对象的管理,它可以将new获得的直接(间接)地址交给它来管理.当我们使用的对象生命周期结束时,它会自动的调用析构函数使用delete释放内存,这时候你再也不用担心内存泄漏了.
那么该如何使用呢?
我们需要包含头文件#include<memory> ,定义的数据类型可以是int,float,double,string,long long......也可以是自己的定义的一些数据类型.下面是我举例智能指针的定义:
//使用智能指针需要的头文件
#include<memory>
//定义了一个int类型智能指针对象age,并分配了10个int类型的数据
auto_ptr<int> age(new int[10]);
//定义了一个string类型的智能指针对象str
auto_ptr<string> str(new string("大佬带带我!我很好带的~"));
//定义了一个使用vector容器装载int类型的智能指针对象auV
auto_ptr<vector<int>> auV(new vector<int>(10));
这些我们定义的智能指针对象,在他们的声明周期结束时,他们会被自动的调用析构函数使用delete释放内存.
智能智能虽然好用,但是我们也需要注意几个点:
1.尽量不要将auto_ptr智能指针定义为全局变量.要知道很多其他的变量我们也是不建议定义为全局变量的.
2.不要定义指向智能指针对象的指针变量.智能指针本身就是一个指针,所以不建议再次定义为指针.使用过程中这会发生一些不可预料的诡异问题.例如:
auto_ptr<int>* age;//不建议将智能指针定义为指针
auto_ptr<int>* age = new auto_ptr<int>(new int[10]);//不建议
//需要使用头文件
#include<memory>//auto_ptr
#include<vector>
//这是一个仅供举例说明的类
class Test {
public:
Test() {
}
~Test() {
}
int getDebug() {
return debug;
}
private:
int debug;
};
int main1(void) {
//不要定义指向智能指针对象的指针变量
auto_ptr<Test>* at = new auto_ptr<Test>(new Test());
}
3.不要把auto_ptr 智能指针赋值给同类型的另外一个智能智能指针,除非你知道这样做的后果,否则不建议这样做.例:
auto_ptr<Test> t1;
auto_ptr<Test> t2;
t1 = t2;//不建议
下面是auto_ptr 的一些常见用法:
//使用智能指针访问对象时,使用方式和普通指针一样,
cout << "t1->getDebug()" << t1->getDebug() << endl;
cout << "(*t1).getDebug()" << (*t1).getDebug() << endl;
//把t1的地址交给了tmp管理
Test* tmp = t1.get();
cout << "tmp->getDebug()" << tmp->getDebug() << endl;
//release 取消指针对动态内存的托管,之前分配的内存需要使用delete手动释放!
tmp = t1.release();
delete tmp;
//reset 重置智能指针托管的内存,如果地址不一致,之前的地址会被析构掉
t1.reset();
t1.reset(new Test());
另外说一下,auto_ptr 在 C++11 标准出来之后就被"抛弃"了,使用更安全的unique_ptr替代.大家会说这都不用了说还有什么用呢?
但了解auto_ptr可以更好的了解unique_ptr,后面我会讲一下unique_ptr。那今天的分享就到这里了。