c++ auto_ptr智能指针
c++ auto_ptr智能指针
该类型在头文件memory中,在程序的开通通过 #include<memory> 导入,接下来讲解该智能指针的作用和使用。
使用方法:
auto_ptr<type> ptr(new type()); 这是该指针的定义形式,其中 type 是指针指向的类型,ptr 是该指针的名称。
比如该type 是int,具体定义如下:
auto_ptr<int> ptr(new int(4));
比如该type 是map<int,vector<int> >,具体定义如下:
auto_ptr<map<int,vector<int> > > ptr(new map<int,vector<int> > ());
当然可以先定义,后赋值,如下所示:
auto_ptr<map<int,int> > ptr;
ptr = auto_ptr<map<int,int> >(new map<int,int> ());
作用1:保证一个对象在某个时间只能被一个该种类型的智能指针所指向,就是通常所说的对象所有权。
作用2:对指向的对象自动释放的作用,详情看如下代码。
代码片段一:
#include <iostream> #include <string.h>
#include <memory>
#include <string>
#include <Windows.h>
#include <map> #include <ctime>
#include <vector>
using namespace std;#define MAXN 20000000 class test_ptr
{
public:
map<int,int> *p;
test_ptr()
{
p = new map<int,int>();
for(int i = ;i<MAXN;i++)
p->insert(make_pair(i,i));
}
}; int main(int argc,char *argv[])
{
for(int i = ;i<;i++)
{
Sleep();
cout << i << endl; // 输出 创建次数
test_ptr * tmp = new test_ptr(); } system("pause");
return ;
}
在某些情况下,可能我们就会写出上面的代码来,通过运行会发现存在内存溢出。对于一些经验老道的程序员可能会作如下改写:
代码片段二:
#include <iostream> #include <string.h>
#include <memory>
#include <string>
#include <Windows.h>
#include <map>
#include <ctime>
#include <vector> using namespace std; #define MAXN 20000000 class test_ptr
{
public:
map<int,int> *p;
test_ptr()
{
//p = auto_ptr<map<int,int> > (new map<int,int>());
p = new map<int,int>();
for(int i = ;i<MAXN;i++)
p->insert(make_pair(i,i));
} ~test_ptr()
{
delete p;
} }; int main(int argc,char *argv[])
{
for(int i = ;i<;i++)
{
Sleep();
cout << i << endl;
test_ptr * tmp = new test_ptr(); } system("pause");
return ;
}
在test_ptr 类中的析构函数中添加内存释放代码,但是在main函数中,定义的局部指针,当局部指针失效时并不会自动调用析构函数,在这种情况下也会导致内存泄漏问题。当然,如果细心的程序员可以在 test_ptr * tmp = new test_ptr() 后面加上一句 delete tmp ,这样也能够释放内存,不会出现内存泄漏问题。但是在某些情况下,很容易漏写,为了解决此问题,auto_ptr 就能发挥作用了。
代码片段三:
#include <iostream> #include <string.h>
#include <memory>
#include <string>
#include <Windows.h>
#include <map>
#include <ctime>
#include <vector> using namespace std; #define MAXN 20000000 class test_ptr
{
public:
map<int,int> *p;
test_ptr()
{
p = new map<int,int>();
for(int i = ;i<MAXN;i++)
p->insert(make_pair(i,i));
} ~test_ptr()
{
delete p;
} }; int main(int argc,char *argv[])
{
for(int i = ;i<;i++)
{
Sleep();
cout << i << endl; //输出创建次数
auto_ptr<test_ptr> tmp = auto_ptr<test_ptr> (new test_ptr()); } system("pause");
return ;
}
在main函数中,创建test_ptr类型指针时,该指针是auto_ptr 类型的智能指针,当智能指针失效时,会自动调用该类的析构函数。所以这种写法可以不再显示调用delete 语句了。但是该智能指针也只是保证调用类的析构函数,如果析构函数并没有释放类中声明的变量,那该怎么办。
代码片段四:
#include <iostream> #include <string.h>
#include <memory>
#include <string>
#include <Windows.h>
#include <map>
#include <ctime>
#include <vector> using namespace std; #define MAXN 20000000 class test_ptr
{
public:
//auto_ptr<map<int,int> > p;
map<int,int> *p;
test_ptr()
{
//p = auto_ptr<map<int,int> > (new map<int,int>());
p = new map<int,int>();
for(int i = ;i<MAXN;i++)
p->insert(make_pair(i,i));
}
/*
~test_ptr()
{
delete p;
}
*/
}; int main(int argc,char *argv[])
{
for(int i = ;i<;i++)
{
Sleep();
cout << i << endl; //输出创建次数
auto_ptr<test_ptr> tmp = auto_ptr<test_ptr> (new test_ptr()); } system("pause");
return ;
}
在这种情况下,还是会出现内存泄漏问题,为了解决该问题,对类中声明的指针也是需要声明为auto_ptr类型。
代码片段五:
#include <iostream> #include <string.h>
#include <memory>
#include <string>
#include <Windows.h>
#include <map>
#include <ctime>
#include <vector> using namespace std; #define MAXN 20000000 class test_ptr
{
public:
auto_ptr<map<int,int> > p;
test_ptr()
{
p = auto_ptr<map<int,int> > (new map<int,int>());
for(int i = ;i<MAXN;i++)
p->insert(make_pair(i,i));
} }; int main(int argc,char *argv[])
{
for(int i = ;i<;i++)
{
Sleep();
cout << i << endl; //输出创建次数
auto_ptr<test_ptr> tmp = auto_ptr<test_ptr> (new test_ptr()); } system("pause");
return ;
}
这样就不用显示定义类的析构函数,不用在外部显示调用delete函数,当然如果尽早调用delete函数也是可以的,尽早释放内存也比该指针失效再释放好一些,这些就是为了防止忘记调用。
通过如上分析:可以得出如下结论。
1 定义了智能指针,当智能指针失效时会自动调用类的析构函数。
2 在 类中定义的智能指针,不必在析构函数中显示的delete,当外部调用该类的析构函数时,会自动释放该智能指针指向的对象,释放内存。
3 如果类中定义的是智能指针,但是外部没有触发类中的析构函数调用,该智能指针指向的对象还是不能释放。
auto_ptr 智能指针的bug
auto_ptr 智能指针在c++ 11 标准中已经被抛弃,被抛弃的原因就是因为该bug。前面也提到过,一个对象只能被一个智能指针所引用,这样就会导致一个赋值问题。看如下代码
代码片段六:
#include <iostream> #include <string.h>
#include <memory>
#include <set> using namespace std; #define MAXN 20000000 void pri(auto_ptr<set<int> > p)
{
set<int>::iterator ite = p->begin();
for(;ite!=p->end();ite++)
{
cout << *ite << endl;
}
} int main(int argc,char *argv[])
{
auto_ptr<set<int> > ptr(new set<int> ()); for(int i = ;i< ;i++)
{
int a;
cin >> a;
ptr->insert(a);
} pri(ptr); pri(ptr); system("pause");
return ;
}
初看这代码没什么问题,不过运行程序会崩溃。这就是该智能指针最大的bug, 在程序32行 调用pri(ptr) ,程序到这并没什么问题,但是第二次调用pri(ptr) 时程序就会崩溃。原因就是前面讲过,一个对象智能被一个智能指针所指向,在第一次调用pri()函数时,为了保证这一原则,当把ptr指针传入pri函数时,程序内部就把ptr置为空,所以到第二次调用时,就会出现崩溃的情况。对于这种情况的解决之道就是使用shared_ptr 指针(该指针的原理是通过引用计数器来实现的)。
如果要使用shared_ptr 智能指针,需要安装boost库,该库还包括许多其他功能。有兴趣的可以尝试以下,该类中的智能指针还是比较好用。也不存在很多其他bug。
有时间再详细介绍boost库中shared_ptr指针
c++ auto_ptr智能指针的更多相关文章
- C++ auto_ptr智能指针的用法
C++中指针申请和释放内存通常采用的方式是new和delete.然而标准C++中还有一个强大的模版类就是auto_ptr,它可以在你不用的时候自动帮你释放内存.下面简单说一下用法. 用法一: std: ...
- c++ auto_ptr 智能指针
c++使用智能指针应该保证无论在何种情况下,只要自己被摧毁,就一定连带释放其所有资源,而由于智能型指针本身就是区域变量, 所以无论是正常退出,还是异常退出,只要函数退出,它就一定销毁 常数型auto_ ...
- shared_ptr 和auto_ptr智能指针
shared_ptr:计数的智能指针 它是一个包装了new操作符在堆上分配的动态对象,但它实现的是引用计数型的智能指针 ,可以被自由地拷贝和赋值,在任意的地方共享它,当没有代码使用(引用计数为0)它时 ...
- 【VS开发】【C++开发】正确使用auto_ptr智能指针
1, auto_ptr类 auto_ptr是一个模板类,定义如下: template <typename Type>class auto_ptr {...}: 它存储的是一个指向Type的 ...
- boost准模板库scoped_ptr指针的使用以及auto_ptr智能指针的对照
首先我们看看scoped_ptr的基本使用,包括了swap(),get(),reset()的使用,重要的提醒是作用域结束的时候会自己主动析构,无需手动的释放资源: #include<boost/ ...
- auto_ptr智能指针
C++的auto_ptr所做的事情,就是动态分配对象以及当对象不再需要时自动执行清理. 使用std::auto_ptr,要#include <memory>.
- 关于智能指针auto_ptr
智能指针auto_ptr和shared_ptr也是面试中经常被问到的一个 感觉看auto_ptr的源码反而更加容易理解一些,因为源码的代码量并不大,而且比较容易理解. 本篇主要介绍auto_ptr 其 ...
- C++中的智能指针(auto_ptr)
实际上auto_ptr 仅仅是C++标准库提供的一个类模板,它与传统的new/delete控制内存相比有一定优势.使用它不必每次都手动调用delete去释放内存.当然有利也有弊,也不是全然完美的. 本 ...
- 智能指针剖析(上)std::auto_ptr与boost::scoped_ptr
1. 引入 C++语言中的动态内存分配没有自动回收机制,动态开辟的空间需要用户自己来维护,在出函数作用域或者程序正常退出前必须释放掉. 即程序员每次 new 出来的内存都要手动 delete,否则会造 ...
随机推荐
- win10开机自动启动小键盘
打开注册表 展开到HKEY_USERS\.DEFAULT\Control Panel\Keyboard 再选择InitialKeyboardIndicators, 将其数值数据修改为2(Win7)/8 ...
- [AIR] 打开我的电脑
import flash.filesystem.File; import flash.desktop.NativeProcess; import flash.desktop.NativeProcess ...
- css相对定位+浮动实现元素位置互换
1.设置元素透明度 opacity:0.5; // w3c filter:alpha(opacity=50); //IE 2 position:relative; float:left; 一起使用的效 ...
- 创建一个List获取数据的lookup
第一步,在类:syslookup中新建方法 public static client void lookupList(FormStringControl _formStringControl, Lis ...
- 对想进入Unity开发新人的一些建议
提前声明:本文只是写给那些非职业游戏开发人士,只面向那些在校本科生,或已就业但无unity背景的同学们,当然是面对程序员方向的.本人刚工作也没多久,资历尚浅,之前在网上有一位同学让我谈谈一些想法,所以 ...
- XXX esx.problem.syslog.nonpersistent.formatOnHost not found XXX
ESXi 主机的摘要选项卡报告以下错误:配置问题:XXX esx.problem.syslog.nonpersistent.formatOnHost 未找到 XXX (2101811) Sympt ...
- mysql常用单行函数
一.大小写控制函数 LOWER(str) 将str的值全部置为小写字母 select LOWER('ABC'); --结果: LOWER('ABC') abc UPPER(str) 将st ...
- QTP操作excel文档
对于QTP操作excel的大前提是,保证组建服务里的DCOM配置里存在 microsoft excel application ,具体的查看方式是,在运行框中输入dcomcnfg,然后会打开组件服务的 ...
- VS中附加进程的方式调试IIS页面,以及设置断点无效问题解决
以前调试网站的时候都习惯是直接在解决方案中右键调试——启动新实例,后来发现这样的缺点有: 1.启动比较慢: 2.一些浏览器的request参数无法带入: 3.不特殊指定启动url的话,VS会将页面加载 ...
- tracert-命令小结
前言:今天在阅读“Web性能权威指南”这本书的时候,发现 tracert 这个命令挺有意思的,在分析网络性能瓶颈的时候也能使用的到,在此就小记一笔以备后用. 1:作用 tracert 是一 ...