C/C++与其他语言相比最大的优势是可以通过指针直接操作内存,速度快。但同样地,C/C++最为人诟病的也是指针使用不当导致的内存泄漏的问题。
因此其实很多语言都内置了内存分配与释放功能,有的甚至对语言的使用者屏蔽了内存指针的概念。也不好说哪种好哪种不好,这其实是两种不同的设计哲学:有人觉得内存如此重要,怎么能放心交给用户管理呢?也有人认为内存如此重要,怎么能放心交给系统管理?
为了解决内存泄漏的问题,各类库和工具一直在努力尝试着用各种方法检测和避免内存泄漏,因此智能指针应运而生。
今天跟大家介绍的是最早的一个智能指针——auto_ptr(C++98/C++03)
现在讨论std::auto_ptr不免让人怀疑是否有点过时了,确实如此,C++11中已经了废弃了auto_ptr,取而代之的是std::unique_ptr。这里之所以介绍auto_ptr的用法及不足之处,是想让大家更好地了解智能指针的发展历程。
std::auto_ptr的基本用法:
#includememoryintmain(){//初始化方式一std::auto_ptrintsp1(newint(8));//初始化方式二std::auto_ptrintsp2;sp2.reset(newint(8));return0;}
在以上代码中,智能指针sp1和sp2均持有一个在堆上分配的int对象,值都为8,这两块堆内存都在sp1和sp2释放时得到释放。这是auto_ptr的基本用法。
auto_ptr的致命缺点
std::auto_ptr容易让人误用的地方是其不常用的复制语义,即当复制一个std::auto_ptr对象时(可以是拷贝构造或者是operator=复制),原std::auto_ptr对象所持有的堆内存对象也会被转移到复制出来的新std::auto_ptr对象。下面给大家看一段代码:
#includeiostream#includememoryintmain(){//测试拷贝构造std::auto_ptrintsp1(newint(8));std::auto_ptrintsp2(sp1);if(sp1.get()!=NULL)std::cout"sp1isnotempty."std::endl;elsestd::cout"sp1isempty."std::endl;if(sp2.get()!=NULL)std::cout"sp2isnotempty."std::endl;elsestd::cout"sp2isempty."std::endl;//测试赋值复制std::auto_ptrintsp3(newint(8));std::auto_ptrintsp4;sp4=sp3;if(sp3.get()!=NULL)std::cout"sp3isnotempty."std::endl;elsestd::cout"sp3isempty."std::endl;if(sp4.get()!=NULL)std::cout"sp4isnotempty."std::endl;elsestd::cout"sp4isempty."std::endl;return0;}
在以上代码中分别利用了拷贝构造(sp1=sp2)和赋值构造(sp3=sp4)来创建新的std::auto_ptr对象,因此sp1持有的堆对象被转移到sp4。
程序执行结果如下红框所示:
因为auto_ptr在c++11中被废弃,C++17中移除,所以编译器会报警告,提醒你用的是过时的auto_ptr。
本次分享到此为止,有问题欢迎评论区提问,下次继续分享智能指针——std::unique_ptr的知识。