为什么要使用智能指针:我们知道c++的内存管理是让很多人头疼的事,当我们写一个new语句时,一般就会立即把delete语句直接也写了,但是我们不能避免程序还未执行到delete时就跳转了或者在函数中没有执行到最后的delete语句就返回了,如果我们不在每一个可能跳转或者返回的语句前释放资源,就会造成内存泄露。使用智能指针可以很大程度上的避免这个问题,因为智能指针就是一个类,当超出了类的作用域是,类会自动调用析构函数,析构函数会自动释放资源。下面我们逐个介绍。 class test { public: test(string s) { str=s; cout<<"Test Create"<<endl; } ~test() { cout<<"delete the sting :"<<str<<endl; } string & getstr() { return str; } string setstr(string s) { str=s; } void print() { cout<<str<<endl; } private: string str; }; int main() { auto_ptr<test> ptest(new test("123")); ptest->setstr("hello"); ptest->print(); ptest->getstr()+="world"; ptest->print(); ptest.reset(new test("123")); ptest.get()->print(); return 0; }
运行结果
Test Create
hello
helloworld
Test Create
delete the sting :helloworld
123
delete the sting :123
int main() { auto_ptr<test> ptest(new test("123")); auto_ptr<test> ptest2(new test("456")); ptest2 = ptest; ptest2->print(); if(ptest.get() == NULL)cout<<"ptest = NULL\n"; return 0; }
运行结果:
Test Create
Test Create
delete the sting :456
123
ptest = NULL
delete the sting :123
如上面的代码:智能指针可以像类的原始指针一样访问类的public成员,成员函数get()返回一个原始的指针,成员函数reset()重新绑定指向的对象,而原来的对象则会被释放。注意我们访问auto_ptr的成员函数时用的是“.”,访问指向对象的成员时用的是“->”。我们也可用声明一个空智能指针auto_ptr<Test>ptest();
当我们对智能指针进行赋值时,如ptest2 = ptest,ptest2会接管ptest原来的内存管理权,ptest会变为空指针,如果ptest2原来不为空,则它会释放原来的资源,基于这个原因,应该避免把auto_ptr放到容器中,因为算法对容器操作时,很难避免STL内部对容器实现了赋值传递操作,这样会使容器中很多元素被置为NULL。判断一个智能指针是否为空不能使用if(ptest == NULL),应该使用if(ptest.get() == NULL)
int main() { shared_ptr<test> ptest(new test("123")); shared_ptr<test> ptest2(new test("456")); cout<<ptest2->getstr()<<endl; cout<<ptest2.use_count()<<endl; ptest = ptest2;//"456"引用次数加1,“123”销毁 ptest->print(); cout<<ptest2.use_count()<<endl;//2 cout<<ptest.use_count()<<endl;//2 ptest.reset(); ptest2.reset();//此时“456”销毁 cout<<"done !\n"; return 0; }
weak_ptr(官方文档)
weak_ptr是用来解决shared_ptr相互引用时的死锁问题,如果说两个shared_ptr相互引用,那么这两个指针的引用计数永远不可能下降为0,资源永远不会释放。它是对对象的一种弱引用,不会增加对象的引用计数,和shared_ptr之间可以相互转化,shared_ptr可以直接赋值给它,它可以通过调用lock函数来获得shared_ptr。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
|