C++ STL学习之auto_ptr

最近在学习opencv源码过程中,发现c++知识忘的差不过了,所以借这个机会在复习一下C++ STL编程。首先记录一下智能指针,在后面学习过程中,会用到智能指针。

1.auto_ptr智能指针

c++的智能指针是比较简单的,简单在于它无法记录当前系统是否还有其它地方引用当前对象,这样的话就无法智能的释放对象。只能在智能指针对象释放时,方能释放引用对象。现在Android中的sp,wp,结合RefBase类,可以实现引用计数。前提是被引用的对象需要继承RefBase,这里就不多说了。

  • 构造函数
  template<typename _Tp>
    class auto_ptr
    {
    private:
      _Tp* _M_ptr;
      
    public:
      /// The pointed-to type.
      typedef _Tp element_type;// 这个_Tp就是初始化时,传进来的模板。
      explicit
      auto_ptr(element_type* __p = 0) throw() : _M_ptr(__p) { }//《1》
      auto_ptr(auto_ptr& __a) throw() : _M_ptr(__a.release()) { }//《2》
      template<typename _Tp1>
        auto_ptr(auto_ptr<_Tp1>& __a) throw() : _M_ptr(__a.release()) { }//《3》
    //.......
    }

如上面可以看到有三种构造函数,《1》是最常用的,进来就把被引用对象的指针赋给_M_ptr对象。《2》这个是同种智能指针,相互传递过程时用,实际需要时,最好使用这种。《3》有定义可以看到,此时模板变成了(_Tp1),但是原始的模板是( _Tp),这样可能会引起转化问题,这不是很安全,少用吧。

  • 重载运算符“*”,“->","="
      auto_ptr&
      operator=(auto_ptr& __a) throw()
      {
	reset(__a.release());
	return *this;
      }
      template<typename _Tp1>
        auto_ptr&
        operator=(auto_ptr<_Tp1>& __a) throw()
        {
	  reset(__a.release());
	  return *this;
	}
     element_type&
      operator*() const throw() 
      {
	_GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
	return *_M_ptr; 
      }
      element_type*
      operator->() const throw() 
      {
	_GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
	return _M_ptr; 
      }

如上面"="运算符,没看到有被引用对象的类型,所以一般看到智能指针是 atuto_ptr<int> p(new int);,“=”运算符可以应用在不同auto_ptr对象转换和应用不同类型引用对象的转换。其它2个运算符,返回的都是被引用对象自己,很好理解额。

  • 方法-release、reset、get
      element_type*
      release() throw()
      {
	element_type* __tmp = _M_ptr;
	_M_ptr = 0;
	return __tmp;
      }
      void
      reset(element_type* __p = 0) throw()
      {
	if (__p != _M_ptr)
	  {
	    delete _M_ptr;
	    _M_ptr = __p;
	  }
      }
      element_type*
      get() const throw() { return _M_ptr; }

release()方法,可以理解成释放当前auto_ptr指针,并返回之前被引用的对象。reset()方法是,重置被引用的地方,可以理解成更换主人了。get()方法即返回当前引用对象。

  • 析构函数
 ~auto_ptr() { delete _M_ptr; }

就这么一行代码,很黄很暴力,所以要特别注意"最好不要多个智能指针引用一个对象,目前智能指针还没那么智能",

##2.测试代码
定义了一个cat类,实现了若干方法。

#include <iostream>
#include <auto_ptr.h>
using namespace std;

class cat {
public:
	cat(int age,char *name):cat_age(age),cat_name(name) {
		cout<<"cat "+cat_name+" in" <<endl;
	}

	void jiao(){
		cout << "miaomiao" << endl;
	}
	void print_age(){
		cout <<"cat age is " << cat_age << endl;
	}
	void print_name(){
		cout << "cat name is:"<< cat_name << endl;
	}
	~cat(){
		cout << "~cat" <<endl;
	}

private:
	int cat_age;
	string cat_name;
};

上面是简单的cat类。

  • demo1
int main() {
	cat* cat1 = new cat(8,"xiao_liu");
	cat* cat2 = new cat(16,"xiao_hua");

	cat1->print_name();
	cat1->print_age();
	cat2->print_name();
	cat2->print_age();
	return 0;
}

上面由于没有手动delete cat1,cat2,所以肯定有内存泄露,从下方运行结果可以发现,没有打印析够函数中的log。

cat xiao_liu in
cat xiao_hua in
cat name is:xiao_liu
cat age is 8
cat name is:xiao_hua
cat age is 16

  • demo2
int main() {
	cat* cat1 = new cat(8,"xiao_liu");
	cat* cat2 = new cat(16,"xiao_hua");

	cat1->print_name();
	cat1->print_age();
	cat2->print_name();
	cat2->print_age();

	auto_ptr<cat> smart_cat1(cat1);
	auto_ptr<cat> smart_cat2(cat2);

	return 0;
}

与demo差别在于,使用智能指针引用cat1和cat2。可以看到下面打印结果。可以发现调用了2次析够方法。非常方便。

cat xiao_liu in
cat xiao_hua in
cat name is:xiao_liu
cat age is 8
cat name is:xiao_hua
cat age is 16
~cat
~cat

  • demo3
int main() {
	auto_ptr<cat> smart_cat1(new cat(8,"xiao_liu"));
	auto_ptr<cat> smart_cat2(new cat(16,"xiao_hua"));
       //一般auto_ptr使用应该在一开始如上面使用,避免对象外泄。后面方法都使用智能
       //指针对象,如果先使用一个cat *指针指向新new出来的对象,如果在一些地方执行
       //了delete操作那么auto_ptr引用的对象就为空,所以要特别注意。
	smart_cat1->print_name();
	smart_cat1->print_age();
	smart_cat2->print_name();
	smart_cat2->print_age();
	cat * cat3 = smart_cat1->get();//如果要拿被引用对象,可以这样做。
	return 0;
}

运行结果:

cat xiao_liu in
cat xiao_hua in
cat name is:xiao_liu
cat age is 8
cat name is:xiao_hua
cat age is 16
~cat
~cat

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值