C++ 智能指针auto_ptr详解
1. auto_ptr 的设计动机:
函数操作经常依照下列模式进行:
- 获取一些资源
- 执行一些动作
- 释放所获取的资源
那么面对这些资源的释放问题就会出现下面的两种情况:
- 一开始获得的资源被绑定于局部对象,那么当函数退出的时候,这些局部对象的析构函数被自动的调用,从而自动释放掉这些资源;
- 一开始获得的资源是通过某种显示手段获取,而且并没有绑定在任何对象身上,那么必须以显式的方式释放。这种情况常常发生在指针身上;
例子:
void f()
{
ClassA* ptr = new ClassA();
...
delete ptr;
}
上述代码的真正的问题在于: 一旦在...中的某处发生异常,那么f()函数将立即退出,根本不会去调用函数尾端的delete语句。结果可能会造成内存的遗失,或者称为资源的遗失。
上述问题的一个解决方案是:
void f()
{
ClassA* ptr = new ClassA(); try
{
...
}
catch(...)
{
delete ptr;
throw;
} delete ptr;
}
为了在异常发生时处理对象的删除工作,程序代码就会变得非常复杂和累赘!
为此,引入了智能指针的概念:
智能指针应该保证:无论在何种情形下,只要自己被销毁,就一定要连带释放其所指向的资源。由于智能指针本身就是区域变量,所以无论是正常推出,还是异常推出,它都一定被销毁,auto_ptr正是这种指针。
auto_ptr是这样的一种指针: 它是"其所指向的对象"的拥有者。所以,当身为对象拥有者的auto_ptr被销毁时,该对象也将被销毁。auto_ptr要求一个对象只能有一个拥有者,严禁一物二主。(天地之间物各有主,苟非吾之所有,虽一毫而莫取)。
下面我们通过一个实例来认识auto_ptr的使用:
#include <iostream>
#include <string>
#include <memory> using namespace std; class Test
{
public:
Test(const string& psg);
string getMsg();
private:
string msg;
}; Test::Test(const string& psg)
{
msg = psg;
} string Test::getMsg()
{
return msg;
} int main(void)
{
std::auto_ptr<Test> ptr(new Test("This is the end of the world!"));
cout<<ptr->getMsg()<<endl;
return ;
}
初始化一个auto_ptr时,将一个指针作为参数传递给auto_ptr的构造函数。而不能使用赋值操作符。
2. auto_ptr拥有权的转移:
auto_ptr所界定的是一种严格的拥有权观念。也就是说,由于一个auto_ptr会删除其所指向的对象,所以这个对象绝对不能被其他对象同时"拥有"。绝对不可以出现多个
auto_ptrs拥有同一个对象。
那么auto_ptr的copy构造函数和assignment操作符该如何运作呢?
另auto_ptr的copy构造函数和assignment操作符将对象的拥有权交出去!
// initialize an auto_ptr with a new object
std::auto_ptr<Test> ptr1(new Test("This is the end of the world!")); // copy the auto_ptr
// ~ transfers ownership from ptr1 to ptr2
std::auto_ptr<Test> ptr2(ptr1); cout<<ptr1->getMsg()<<endl;
上面对象的拥有权从ptr1交到ptr2的时候,再使用ptr1去getMsg的时候,会出现"段错误"提示。
#include <iostream>
#include <string>
#include <memory> using namespace std; class Test
{
public:
Test(const string& psg,const int& id);
~Test();
string getMsg();
private:
string msg;
int id;
}; Test::Test(const string& psg,const int& pid)
{
msg = psg;
id = pid;
} Test::~Test()
{
cout<<"Delete "<<id<<" "<<endl;
} string Test::getMsg()
{
return msg;
} int main(void)
{
std::auto_ptr<Test> ptr1(new Test("This is ptr1",));
std::auto_ptr<Test> ptr2(new Test("This is ptr2",));
ptr2 = ptr1;
return ;
}
上面代码的结果是:
Delete
Delete
表明: 当ptr2被赋值前正拥有另一个对象,赋值动作发生时会发生delete,将该对象删除。
C++ 智能指针auto_ptr详解的更多相关文章
- C++智能指针(auto_ptr)详解
智能指针(auto_ptr) 这个名字听起来很酷是不是?其实auto_ptr 只是C++标准库提供的一个类模板,它与传统的new/delete控制内存相比有一定优势,但也有其局限.本文总结的8个问题足 ...
- c++ 智能指针用法详解
本文介绍c++里面的四个智能指针: auto_ptr, shared_ptr, weak_ptr, unique_ptr 其中后三个是c++11支持,并且第一个已经被c++11弃用. 为什么要使用智能 ...
- 19.C++-(=)赋值操作符、智能指针编写(详解)
(=)赋值操作符 编译器为每个类默认重载了(=)赋值操作符 默认的(=)赋值操作符仅完成浅拷贝 默认的赋值操作符和默认的拷贝构造函数有相同的存在意义 (=)赋值操作符注意事项 首先要判断两个操作数是否 ...
- C++11 shared_ptr(智能指针)详解
要确保用 new 动态分配的内存空间在程序的各条执行路径都能被释放是一件麻烦的事情.C++ 11 模板库的 <memory> 头文件中定义的智能指针,即 shared _ptr 模板,就是 ...
- C++智能指针--auto_ptr指针
auto_ptr是C++标准库提供的类模板,头文件<memory>,auto_ptr对象通过初始化指向由new创建的动态内存,它是这块内存的拥有者,一块内存不能同一时候被分给两个拥有者.当 ...
- 自己动手实现智能指针auto_ptr
面试的时候,我们经常会被问到如何自己动手实现智能指针auto_ptr.今天我就一边参考STL库中的源代码,一边将auto_ptr的实现敲一遍. auto_ptr归根到底是一个模版类,那么这个类要实现哪 ...
- C++ 智能指针auto_ptr
template<class T> class auto_ptr { public: ); // Item M5 有“explicitfor”// 的描述 template<clas ...
- 关于智能指针auto_ptr
智能指针auto_ptr和shared_ptr也是面试中经常被问到的一个 感觉看auto_ptr的源码反而更加容易理解一些,因为源码的代码量并不大,而且比较容易理解. 本篇主要介绍auto_ptr 其 ...
- C++中的智能指针(auto_ptr)
实际上auto_ptr 仅仅是C++标准库提供的一个类模板,它与传统的new/delete控制内存相比有一定优势.使用它不必每次都手动调用delete去释放内存.当然有利也有弊,也不是全然完美的. 本 ...
随机推荐
- 解读(GoogLeNet)Going deeper with convolutions
(GoogLeNet)Going deeper with convolutions Inception结构 目前最直接提升DNN效果的方法是increasing their size,这里的size包 ...
- [置顶] mysql中的set和enum类型的用法和区别
mysql中的enum和set其实都是string类型的而且只能在指定的集合里取值, 不同的是set可以取多个值,enum只能取一个值. CREATE TABLE `20121101_t` ( ...
- AJAX中的dataType(数据格式)-text、json
因为经常使用数据格式,所以将它封装成类,J这样就不会用到时就写了,直接调用写好的类就可以了 (1)dataType数据格式为:TEXT格式的数据是字符串的数据,在"ajax对数据进行删除和查 ...
- jQuery中get与eq的区别
get与eq的区别 .eq() 减少匹配元素的集合,根据index索引值,精确指定索引对象. .get() 通过检索匹配jQuery对象得到对应的DOM元素. 同样是返回元素,那么eq与get有什么区 ...
- asp.net C#母版页和内容页事件排版载入顺序生命周期
asp.net C#母版页和内容页事件排版载入顺序生命周期 关于ASP页面Page_Load发生在事件之前而导致的问题已经喜闻乐见,对于问题的解释也非常全面.可是怎样解决这个问题则较少有人说明,我就再 ...
- javascript Deferred和递归次数限制
function runAsyncTTS(text,speecher,audiopath) { var def = jQuery.Deferred(); var args = {"Synth ...
- linux学习之八---Linux进程基础知识
一.linux进程 linux是一个多用户多任务的操作系统. 多用户是指多个用户能够在同一时间使用计算机. 多任务是指linux能够同一时候运行几个任务. 进程简单来说就是执行中的程序,Linux系统 ...
- 误删/tmp导致hadoop无法启停, jsp无法查看的解决方法
问题描述 我的hadoop版本是hadoop-cdh4.2.0,由于误删了/tmp目录(不是hadoop.tmp.dir设定的那个目录),在Namenode,SecondaryNamenode和Dat ...
- java 拦截器和过滤器区别(转载)
1.拦截器是基于java的反射机制的,而过滤器是基于函数回调 2.过滤器依赖与servlet容器,而拦截器不依赖与servlet容器 3.拦截器只能对action请求起作用,而过滤器则可以对几乎所有的 ...
- SQL Server 阻止了对组件 'Ole Automation Procedures' 的 过程 'sys.sp_OACreate' 的访问
sqlserver2008导入excel到数据库的时候报错: SQL Server 阻止了对组件 'Ole Automation Procedures' 的 过程 'sys.sp_OACreate' ...