小议auto_ptr

原创 2003年06月22日 11:25:00

    小议auto_ptr

 一直以来都以为auto_ptr是个易用的东西,虽然一直都
没有用过它.直到昨天,终于用了一下VC版本的auto_ptr,
结果许多行为令人费解.
 没有办法,又重新把STL参考书研究了一遍,随后把VC版
的auto_ptr源码翻来研究了一番,原来是.....

 有所得,总结了如下一些东东,望对初学者有所帮助.同
时,若有不对的地方望各位大虾多指教.
 
 详细解说见代码注解!

//auto_ptr.h

#ifndef AUTO_PTR__H__
#define AUTO_PTR__H__

//声明:
//1.以下源代码仅供学习.任何使用过程中所造成的后果与作者无关.
//2.如果您使用了,表示您接受该声明

//作者 古斌亮
//时间 2003.06.21
//email: kinglinux@163.com

//vc auto_ptr:仿照VC版的auto_ptr行为写的一个auto_ptr
namespace vc
{
 template<class T>
 class auto_ptr
 {
 public:
  explicit auto_ptr(T * p = NULL):_own(p!=0), _ptr(p){}
  
 public:
  auto_ptr(const auto_ptr<T>& y): _own(y._own), //拥有权转移到目标
   _ptr(y.release()){}
  
  auto_ptr<T>& operator=(const auto_ptr<T>& y)
  {
   if(this!=&y)
   {
    if(_ptr!=y._ptr)//是否同一个对象
    {
     if(_own)//是否具备拥有权
     {
      delete _ptr;
      _ptr = NULL;
     }
     _own = y._own;
    }
    else if(y._own)_own = true;
    _ptr = y.release();//拥有权转移到目标
   }
   return (*this);
  }
  
  ~auto_ptr()
  {
   if(_own)//如果具备拥有权
   {
    delete _ptr;
    _ptr = NULL;
   }
  }

 public:
  T& operator*() const
  {
   return (*_ptr);
  }

  T *operator->() const
  {
   return (_ptr);
  }

 public:
  T * release() const
  {
   ((auto_ptr<T>*)this)->_own = false;//拥有权转移到目标
   return (_ptr);
  }

 private:
  bool _own;//记录是否拥有权
  T *  _ptr;//引用指针
 };
};//namespace vc


//stl auto_ptr:仿照STL版的auto_ptr行为写的一个auto_ptr
namespace stl
{
 template<class T>
 class auto_ptr
 {
 public:
  explicit auto_ptr(T * p = NULL):_ptr(p){}
  
 public:
  auto_ptr(auto_ptr<T>& y):_ptr(y._ptr)//拥有权转移到目标
  {
   y._ptr = NULL;//释放拥有权
  }
  
  auto_ptr<T>& operator=(const auto_ptr<T>& y)
  {
   if(this!=&y)
   {
    if(_ptr)//释放原先拥有的对象
    {
     delete _ptr;
     _ptr = NULL;
    }

    _ptr = y._ptr;//拥有权转移到目标
    y._ptr = NULL;//释放拥有权
   }
   return (*this);
  }
  
  ~auto_ptr()
  {
   delete _ptr;//释放拥有的对象
  }

 public:
  T& operator*() const
  {
   return (*_ptr);
  }

  T *operator->() const
  {
   return (_ptr);
  }

 private:
  T *  _ptr;//指向具备拥有权对象的指针
 };
};//namespace stl

//以下的一个版本是参考<<C++标准程序库>>(The C++ Standard Library)
//Nicolai M.Josuttis 著 侯捷 孟岩 译  2002年9月
//一书 P222 6.8 提出的具备reference的auto_ptr的观点所做的一个版本
//ref auto_ptr:
namespace ref
{
 template<class T>
 class auto_ptr
 {
 public:
  explicit auto_ptr(T * p = NULL):_ptr(p),_count(new unsigned long(1)){}
  
 public:
  auto_ptr(auto_ptr<T>& y):_ptr(y._ptr),_count(y.addref()){}//增加引用计数
  
  auto_ptr<T>& operator=(auto_ptr<T>& y)
  {
   if(this!=&y)
   {
    if(_ptr!=y._ptr)//是否同一个对象
    {
     release();//释放自己原来的拥有权,这一步
     _ptr = y._ptr;
     _count = y.addref();//增加引用计数
    }
   }
   return (*this);
  }
  
  ~auto_ptr()
  {
   release();//释放拥有权
  }

  T& operator*() const
  {
   return (*_ptr);
  }

  T *operator->() const
  {
   return (_ptr);
  }

  unsigned long * addref(void)//增加引用计数
  {
   ++(*_count);
   return (_count);
  }

 private:
  void release(void)
  {
   if(--(*_count)==0)//减少引用计数并测试引用计数是否为0
   {
    delete _ptr;
    delete _count;
   }
   _count = NULL;//释放引用计数器
   _ptr = NULL;//释放拥有权
  }

 private:
  T *     _ptr;//引用对象指针
  unsigned long *  _count;//引用计数器指针
 };
};//namespace ref

//以上3个版本都是仿照现在比较大众化的被普遍接受的auto_ptr行为的
//简单实现.
//在应用上,用具备引用计数的auto_ptr的是比较好的.

//对于auto_ptr的实现还有许多方法,特别是可以依据在不同的应用场合
//实现不同的版本以改变auto_ptr的行为,让它更适合于我们的应用.
//如在自己的类库中完全可以用基类来做引用计数从而实现安全的
//具备引用计数的auto_ptr
//又如可以用template<>的方法为要装载的类加一个引用计数来实现
//具备引用计数的auto_ptr

//the end.

#endif //AUTO_PTR__H__

//以下是VC6下的测试程序

//dog.h

#ifndef DOG__H__
#define DOG__H__

#include <iostream>
#include <string>

//测试类
class dog
{
public:
 dog(std::string name = "NoName"):_name(name)
 {
  std::cout<<"dog::dog()"<<std::endl;
 }

 ~dog()
 {
  std::cout<<"dog::~dog()"<<std::endl;
 }

public:
 void bark(void)
 {
  std::cout<<_name<<" always bark at rose."<<std::endl;
 }

public:
 void Name(const std::string& name)
 {
  _name = name;
 }

 std::string Name(void)
 {
  return _name;
 }

private:
 std::string  _name;
};

#endif //DOG__H__

//main.cpp

#include <iostream>
#include <string>

#include "auto_ptr.h"
#include "dog.h"

/////////////////////////////////////////
//test vc auto_ptr
void test_vc_fun(void)
{
 std::cout<<"=== test vc auto_ptr ==="<<std::endl;

 vc::auto_ptr<dog> ptom(new dog("Tom"));

 {
  vc::auto_ptr<dog> pjack(ptom);
  ptom = pjack; //1.
  pjack->Name("Jack");
  pjack->bark();
  pjack->Name("Tom");
 }
 ptom->bark();//因为有1.=>successful,如果去掉1.=>error
}


/////////////////////////////////////////
//test stl auto_ptr
void test_stl_fun(void)
{
 std::cout<<"=== test stl auto_ptr ==="<<std::endl;

 stl::auto_ptr<dog> ptom(new dog("Tom"));

 {
  stl::auto_ptr<dog> pjack(ptom);
  pjack->Name("Jack");
  pjack->bark();
 }
 //ptom->bark();//error
}

/////////////////////////////////////////
//test ref auto_ptr
void test_ref_fun(void)
{
 std::cout<<"=== test ref auto_ptr ==="<<std::endl;

 ref::auto_ptr<dog> ptom(new dog("Tom"));

 {
  ref::auto_ptr<dog> pjack(ptom);
  pjack->Name("Jack");
  pjack->bark();
 }

 ptom->bark();//successful
}

void main(void)
{
 std::cout<<"Hello,the world!"<<std::endl;
 test_vc_fun();
 test_stl_fun();
 test_ref_fun();
}

//the end

 

auto_ptr到底能不能作为容器的元素?

【摘要】对C++语言本身来说,它并不在乎用户把什么类型的对象作为STL容器的元素,因为模板类型参数在理论上可以为任何类型。比如说STL容器仅支持“值”语义而不支持“引用(&)”语义,并非因为模板类型参...
  • ysu108
  • ysu108
  • 2014年09月10日 09:38
  • 693

C++ boost智能指针auto_ptr

auto_ptr是当前C++标准库中提供的一种智能指针,或许相对于boost库提供的一系列眼花缭乱的智能指针,这个不怎么智能的智能指针难免会黯然失色。诚然,auto_ptr有这样那样的不如人意,以至于...
  • u011676589
  • u011676589
  • 2013年08月30日 16:40
  • 1096

c++中的智能指针auto_ptr解析

c++中的auto_ptr是一个类,却可以像指针一样去使用。使用auto_ptr需要包含头文件#include 例如:auto_ptr ps(new string("hello"));可以像指针一样...
  • uestclr
  • uestclr
  • 2016年05月06日 10:56
  • 1609

auto_ptr的release的含义

我一直以为auto_ptr的release函数会调用delete操作符删除 其所包含的指针,今天才搞清楚,release函数只是简单的释放其对指针的拥有权。...
  • swordmanwk
  • swordmanwk
  • 2011年01月30日 14:31
  • 3729

std::auto_ptr的原理及使用

使用auto_ptr作为成员变量,以避免资源泄漏。防止资源泄漏,我们通常在构造函数中申请,析构函数中释放,但是只有构造函数调用成功,析构函数才会被调用,换句话说,如果在构造函数中产生了异常,那么析构函...
  • makenothing
  • makenothing
  • 2015年11月13日 17:38
  • 3920

c++智能指针:auto_ptr shared_ptr

1. 简介 C++程序员最痛苦的莫过于对内存的管理,由于没有像C# 和 java的内存回收机制,C++程序员在复杂的程序中容易造成内存的泄露。即使程序员十分小心,异常的产生也有可能会造成部分内存的泄...
  • gui694278452
  • gui694278452
  • 2015年06月03日 18:44
  • 2880

std::auto_ptr 不能赋值 简析

今天试用了下std::auto_ptr, 第一次使用就出错了,尴尬啊,先还原现场:类内声明:Std::auto_ptr m_pWgt;类构造函数内赋值:m_pWgt = new Widget;大概就是...
  • webScaler
  • webScaler
  • 2010年09月18日 12:28
  • 2584

浅谈auto_ptr智能指针

在c++标准库里主要有三个智能指针: ①auto_ptr 在任何情况下都不要使用 ②scoped_ptr 独占空间,防拷贝和赋值,是对第①个智能指针的缺陷所作出的解决 ③shared_ptr 利用...
  • qq_34992845
  • qq_34992845
  • 2017年04月02日 00:20
  • 1113

auto_ptr使用总结

 (1) auto_ptr的意义 auto_ptr是一种智能指针,当系统异常退出的时候避免资源泄漏(内存)。 其他的资源还对应其他的智能指针。 (2) auto_ptr的使用 std::...
  • wangwenwen
  • wangwenwen
  • 2014年11月24日 15:14
  • 776

智能指针:从std::auto_ptr到std::unique_ptr

std::auto_ptr封装动态申请对象内存返回的指针,并且其行为也和普通指针一样。最重要的一点,程序员不必记得去释放之前申请的内存,当std::auto_ptr销毁时,其封装的指针所指向的内存也会...
  • hanhuili
  • hanhuili
  • 2012年12月15日 21:38
  • 5606
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:小议auto_ptr
举报原因:
原因补充:

(最多只允许输入30个字)