谈到智能指针之前,必须要知道堆栈的相关思想,堆栈在程序开发过程中经常使用到的。比如应用程序的函数当中通过new一个对象,这个对象的实际存储地方是在堆上,而它的指针是保存在栈,在函数执行完毕之后,该对象的指针会被自动从栈中弹出,而其指向的对象会在不会被自动释放,需要通过delete函数来释放该指针所指向的堆栈内存。在开发过程中往往因为忘记delete而造成内存泄露的情况。由此就有智能指针的出现。
智能指针主要思想是:在栈中new一个智能指针对象,而这个智能指针对象指向的实际内容是放在堆上的,在函数执行完成之后,该智能指针对象会被从栈中弹出,此时会调用智能指针的析构函数,在执行该析构函数时,会调用delete函数来释放其指向堆栈上的内存。
智能指针的内不实现使用了explicit关键字,该关键值得作用是不用自动将其他其它类型的指针转换成智能指针对象。例如:
shared_ptr<double> pd;
double* p_reg=new double;
pd=p_reg; //not allowed (implicit conversion)
pd=shared_ptr<double>(p_reg) //allowed (explicit conversion)
shared_ptr<double> pshared=p_reg //not allowed (implicit conversion)
shared_ptr<double>pshared(p_reg) //allowed (explicit conversion)
在使用智能指针时,对象所有权的相关注意事项(待续。。。):
auto_ptr<T>智能指针是在赋值操作的同时也将进行所有权的移交,例如:auto_ptr<string> pfirst(new string("This is test string")); auto_ptr<string>psecond=pfirst;该赋值操作完成之后pfirst就不对"This is test string"具有所用权了。如果将pfirst所指向的内容打印出来会随着系统不同而不同,此时psecond具有"This is test string"的所有权,这就是所有权的移交[所有权模型]。
shared_ptr<T>智能指针是通过引用计数的方式来实现内存的释放,例如:shared_ptr<string> pfirst(new string("This is test string")); shared_ptr<string>psecond=pfirst;在执行该赋值操作时,引用计数从1增加到2,在运行结束时后声明的变量psecond首先调用析构函数,引用计数从2降低到1,,最后调用pfirst析构函数,引用计数从1降低到0,堆上的内存被自动释放。
unique_ptr<T>和auto_ptr<T>一样是使用所有权模型,它们的区别在于auto_ptr<T>是在运行阶段程序崩溃,而unique_ptr<T>是在编译阶段就会出现错误,编译不通过。unique_ptr<T>比auto_ptr<T>更加安全,不会留下悬挂的指针。
在试图将一个unique_ptr<T>赋值给另一个时,如果源unique_ptr<T>是一个临时的右值,编译器是允许这样做的,如果源unique_ptr<T>存在一段时间,编译器是不允许这样做的。例如一下代码是能够编译通过的:
unique_ptr<string> demoFunc(const char* str) { unique_ptr<string> temp(new string(str)); return temp; } unique_ptr<string> ps; ps=demo("Uniquely special");