auto_ptr
C++中的一种智能指针实现,auto_ptr被定义为一个模板类。C++11中已经废弃了。
auto_ptr定义如下:
template<class X> class auto_ptr { public: typedef X element_type; explicit auto_ptr(X* p =0) throw(); auto_ptr(auto_ptr&) throw(); template<class Y> auto_ptr(auto_ptr<Y>&) throw(); auto_ptr& operator=(auto_ptr&) throw(); template<class Y> auto_ptr& operator=(auto_ptr<Y>&) throw(); auto_ptr& operator=(auto_ptr_ref<X> r) throw(); ~auto_ptr() throw(); typename add_lvalue_reference<X>::type operator*() const throw(); X* operator->() const throw(); X* get() const throw(); X* release() throw(); void reset(X* p =0) throw(); auto_ptr(auto_ptr_ref<X>) throw(); template<class Y> operator auto_ptr_ref<Y>() throw(); template<class Y> operator auto_ptr<Y>() throw(); };
构造
auto_ptr的构造除了特殊的拷贝构造函数,提供了两种构造,一个是直接通过一个对象指针来构造auto_ptr,另一个是通过一个auto_ptr_ref来构造auto_ptr。
直接通过对象指针构造
explicit auto_ptr(X* p =0) throw();
传入一个指针构造一个auto_ptr,传入的指针参数类型由类模板参数决定,这里指定了一个默认值。需要注意的是,这个构造函数指定了“ explicit”。
参考下面的实现,这种构造方式仅仅是将一个对象指针赋值给auto_ptr内部维护的_M_ptr,auto_ptr通过它对指针进行管理。
explicit auto_ptr(element_type* __p = 0) throw() : _M_ptr(__p) { }
传给__p的对象指针必须是通过new创建。
构造示例
这种形式的构造最简单的就是:
std::auto_ptr<int> p;
int *i = new int(100);
std::auto_ptr<int> p(i);
因为这种构造函数形式指定了“ explicit”,所以不能写成以下形式:
int *i = new int(100);
std::auto_ptr<int> p = i;
通过auto_ptr_ref构造
auto_ptr(auto_ptr_ref<X>) throw();
这通过一个auto_ptr_ref(auto_ptr引用)构造一个auto_ptr。
auto_ptr(auto_ptr_ref<element_type> __ref) throw() : _M_ptr(__ref._M_ptr) { }
拷贝构造
auto_ptr(auto_ptr&) throw();
这是一个拷贝构造
auto_ptr(auto_ptr& __a) throw() : _M_ptr(__a.release()) { }
template<class Y> auto_ptr(auto_ptr<Y>&) throw();
这也是一个拷贝构造,但这个构造是一个模板方法,实现和上面的拷贝构造其实是一样的。
template<typename _Tp1> auto_ptr(auto_ptr<_Tp1>& __a) throw() : _M_ptr(__a.release()) { }
析构
析构的时候只是简单的销毁这个指针指向的对象。
~auto_ptr() { delete _M_ptr; }
操作符重载
重载*(指针)操作符
typename add_lvalue_reference<X>::type operator*() const throw();
通过*操作符可以解引用访问到指向的对象,如*p。
重载->操作符
X* operator->() const throw();
通过->操作符可以将一个auto_ptr变量当成一个指针,进而访问对象成员,这用于类,结构体等类型。
重载=操作符
有3中定义:
auto_ptr& operator=(auto_ptr&) throw();
将一个auto_ptr赋值给另一个auto_ptr。
template<class Y> auto_ptr& operator=(auto_ptr<Y>&) throw();
将一个auto_ptr<Y>类型赋值给auto_ptr。
auto_ptr& operator=(auto_ptr_ref<X> r) throw();
将一个auto_ptr_ref赋值给auto_ptr。
还有两个看似操作符重载的用于隐式转换函数,这是一种“conversion function”,即类型“转换函数”。
template<class Y> operator auto_ptr_ref<Y>() throw();
将一个auto_ptr类型隐式转换为auto_ptr_ref<Y>类型
template<class Y> operator auto_ptr<Y>() throw();
将一个auto_ptr类型隐式转换为auto_ptr<Y>类型
这种操作符重载来实现隐式转换不多见,这个也许用来模拟实现装箱/拆箱或许不错,必须将char、int、long、float、double对应的Char、Integer、Long、Float、Double的class类型对象通过这种隐式类型转换为对应的char、int、long、float、double类型,是一个很巧妙的设计以实现拆箱效果。实际到底是否需要这么做还得结合实际商榷。不管怎么说,这里来个这样的示例:
class Integer { private: int v; public: Integer(int _v) : v(_v) { } };
在上面的例子中,定义了一个int类型对应的类Integer,我们可以通过一个int参数构造一个Integer对象,如下:
Integer i(1);
但上面的代码不能将一个Integer对象转换为int类型,如下:
int _i = i;
要实现以上的转换,可以通过操作符重载来实现隐式转换
operator int() { return v; }
这样就可以实现将一个Integer对象转换为int类型。
int _i = i;
实际上就调用了operator int()重载函数来实现隐式转换以达到拆箱效果,上面的代码等同于:
int _i = i.operator int();
release
释放(release)并不会销毁维护的这个指针指向的对象。只是将维护的这个指针置为0,也就是设置为NULL。释放(release)之后不能在通过这个auto_ptr去操作这个指针指向的对象。但返回的时候会返回原先维护的这个指针,这个指针还有效,这个指针指向的对象并没有被销毁。
element_type* release() throw() { element_type* __tmp = _M_ptr; _M_ptr = 0; return __tmp; }
在上面的构造示例中,可以根据release的返回值重新构造一个auto_ptr,如下:
std::auto_ptr<int> p2(p.release());
这个时候就不能再通过p来操作维护的这个指针指向的对象,但可以通过p2来操作维护的这个指针指向的对象。
auto_ptr_ref
在构造auto_ptr的时候可以通过一个auto_ptr_ref(auto_ptr引用)来构造一个auto_ptr。
template <class Y> struct auto_ptr_ref {};
这个引用实际并不会直接构造。我们可以直接将一个auto_ptr变量赋值给auto_ptr_ref变量,这里可以通过__ptr_访问到引用的对象指针。如下:
int *i = new int(100);
std::auto_ptr<int> p(i);
std::auto_ptr_ref<int> p_ref = p;
这实际上用到操作符auto_ptr_ref<Y>重载:
template<class Y> operator auto_ptr_ref<Y>() throw();
注意这里会释放(release)掉p引用的指针,这意味着不能再使用p。
具体定义如下:
template <class _Tp> struct auto_ptr_ref { _Tp* __ptr_; };
参考libstdc++-v3/include/backward/auto_ptr.h
template<typename _Tp> class auto_ptr { private: _Tp* _M_ptr; public: /// The pointed-to type. typedef _Tp element_type; /** * @brief An %auto_ptr is usually constructed from a raw pointer. * @param __p A pointer (defaults to NULL). * * This object now @e owns the object pointed to by @a __p. */ explicit auto_ptr(element_type* __p = 0) throw() : _M_ptr(__p) { } /** * @brief An %auto_ptr can be constructed from another %auto_ptr. * @param __a Another %auto_ptr of the same type. * * This object now @e owns the object previously owned by @a __a, * which has given up ownership. */ auto_ptr(auto_ptr& __a) throw() : _M_ptr(__a.release()) { } /** * @brief An %auto_ptr can be constructed from another %auto_ptr. * @param __a Another %auto_ptr of a different but related type. * * A pointer-to-Tp1 must be convertible to a * pointer-to-Tp/element_type. * * This object now @e owns the object previously owned by @a __a, * which has given up ownership. */ template<typename _Tp1> auto_ptr(auto_ptr<_Tp1>& __a) throw() : _M_ptr(__a.release()) { } /** * @brief %auto_ptr assignment operator. * @param __a Another %auto_ptr of the same type. * * This object now @e owns the object previously owned by @a __a, * which has given up ownership. The object that this one @e * used to own and track has been deleted. */ auto_ptr& operator=(auto_ptr& __a) throw() { reset(__a.release()); return *this; } /** * @brief %auto_ptr assignment operator. * @param __a Another %auto_ptr of a different but related type. * * A pointer-to-Tp1 must be convertible to a pointer-to-Tp/element_type. * * This object now @e owns the object previously owned by @a __a, * which has given up ownership. The object that this one @e * used to own and track has been deleted. */ template<typename _Tp1> auto_ptr& operator=(auto_ptr<_Tp1>& __a) throw() { reset(__a.release()); return *this; } /** * When the %auto_ptr goes out of scope, the object it owns is * deleted. If it no longer owns anything (i.e., @c get() is * @c NULL), then this has no effect. * * The C++ standard says there is supposed to be an empty throw * specification here, but omitting it is standard conforming. Its * presence can be detected only if _Tp::~_Tp() throws, but this is * prohibited. [17.4.3.6]/2 */ ~auto_ptr() { delete _M_ptr; } /** * @brief Smart pointer dereferencing. * * If this %auto_ptr no longer owns anything, then this * operation will crash. (For a smart pointer, <em>no longer owns * anything</em> is the same as being a null pointer, and you know * what happens when you dereference one of those...) */ element_type& operator*() const throw() { __glibcxx_assert(_M_ptr != 0); return *_M_ptr; } /** * @brief Smart pointer dereferencing. * * This returns the pointer itself, which the language then will * automatically cause to be dereferenced. */ element_type* operator->() const throw() { __glibcxx_assert(_M_ptr != 0); return _M_ptr; } /** * @brief Bypassing the smart pointer. * @return The raw pointer being managed. * * You can get a copy of the pointer that this object owns, for * situations such as passing to a function which only accepts * a raw pointer. * * @note This %auto_ptr still owns the memory. */ element_type* get() const throw() { return _M_ptr; } /** * @brief Bypassing the smart pointer. * @return The raw pointer being managed. * * You can get a copy of the pointer that this object owns, for * situations such as passing to a function which only accepts * a raw pointer. * * @note This %auto_ptr no longer owns the memory. When this object * goes out of scope, nothing will happen. */ element_type* release() throw() { element_type* __tmp = _M_ptr; _M_ptr = 0; return __tmp; } /** * @brief Forcibly deletes the managed object. * @param __p A pointer (defaults to NULL). * * This object now @e owns the object pointed to by @a __p. The * previous object has been deleted. */ void reset(element_type* __p = 0) throw() { if (__p != _M_ptr) { delete _M_ptr; _M_ptr = __p; } } /** * @brief Automatic conversions * * These operations are supposed to convert an %auto_ptr into and from * an auto_ptr_ref automatically as needed. This would allow * constructs such as * @code * auto_ptr<Derived> func_returning_auto_ptr(.....); * ... * auto_ptr<Base> ptr = func_returning_auto_ptr(.....); * @endcode * * But it doesn't work, and won't be fixed. For further details see * http://cplusplus.github.io/LWG/lwg-closed.html#463 */ auto_ptr(auto_ptr_ref<element_type> __ref) throw() : _M_ptr(__ref._M_ptr) { } auto_ptr& operator=(auto_ptr_ref<element_type> __ref) throw() { if (__ref._M_ptr != this->get()) { delete _M_ptr; _M_ptr = __ref._M_ptr; } return *this; } template<typename _Tp1> operator auto_ptr_ref<_Tp1>() throw() { return auto_ptr_ref<_Tp1>(this->release()); } template<typename _Tp1> operator auto_ptr<_Tp1>() throw() { return auto_ptr<_Tp1>(this->release()); } } _GLIBCXX11_DEPRECATED_SUGGEST("std::unique_ptr");
示例,在下面的例子中,在main函数返回时,指针变量i指向的new申请的内存将被自动释放,因为在main函数返回时会隐式调用p的析构函数,auto_ptr的析构函数会负责将维护的这个指针指向的对象内存释放。
#include <iostream> #include <memory> int main() { int *i = new int(100); std::auto_ptr<int> p(i); std::cout<<"i="<<*p<<std::endl; return 0; }
相关推荐
在 C++ 中,有四种智能指针:auto_ptr、unique_ptr、shared_ptr 和 weak_ptr,每种智能指针都有其特点和使用场景。 一、auto_ptr auto_ptr 是 C++98 中引入的智能指针,它可以自动释放动态分配的内存。但是,auto_...
该文档是C++ auto_ptr源码,感兴趣的可以自行下载学习。
详细讨论c++ auoto_ptr的原型,用法,以及注意事项
标题中的“自己实现的auto_ptr”指的是用户自行编写的一个智能指针类,模仿了C++标准库中的`std::auto_ptr`。`std::auto_ptr`是C++标准库中的一个智能指针,用于管理动态分配的对象,它会在适当的时候自动删除所指向...
尽管在C++11及以后版本中引入了更强大的智能指针如`unique_ptr`和`shared_ptr`,但了解`auto_ptr`的基本概念和用法对于理解智能指针仍然非常重要。 #### `auto_ptr`的概念与作用 `auto_ptr`主要用来管理动态分配的...
标题与描述均提到“auto_ptr再回忆”,暗示文章将通过一个故事的形式,回顾与探讨C++中`auto_ptr`的使用及其潜在问题。`auto_ptr`是C++标准库中的一个智能指针类,用于自动管理动态分配的资源,当`auto_ptr`对象超出...
该文档是C++ auto_ptr源码,感兴趣的可以自行下载学习,方便大家学习参考。
### C++ 智能指针 Auto_PTR 的细致而经典分析 #### 一、引言 C++ 是一门强大而灵活的语言,它不仅为开发者提供了底层控制能力,还通过多种高级特性来帮助开发者提高代码质量和可维护性。其中一项重要的功能就是...
在C++11之后,`auto_ptr`已被`unique_ptr`取代,因为`auto_ptr`有一些限制和潜在的问题,但在理解C++的历史和发展时,学习`auto_ptr`仍然是有价值的。 **1. `auto_ptr`的基本概念** `auto_ptr`是一个类模板,它包装...
其中,`auto_ptr`是C++98标准库中提供的一个智能指针类型,但在C++11及更高版本中已被推荐弃用,取而代之的是`unique_ptr`。尽管如此,理解`auto_ptr`的工作原理仍然是学习C++历史和理解智能指针概念的重要部分。 `...
本文将深入探讨C++中的`auto_ptr`,一种早期的智能指针,尽管在C++11标准中已被`unique_ptr`取代,但它仍然是理解智能指针工作原理的良好起点。 智能指针的基础原理在于,它是一个类,能够通过构造函数绑定到一个...
实际上auto_ptr 仅仅是C++标准库提供的一个类模板,它与传统的new/delete控制内存相比有一定优势。使用它不必每次都手动调用delete去释放内存。当然有利也有弊,也不是全然完美的。 本文从以下的8个方面来总结...
`shared_ptr`是C++11中引入的智能指针之一,它使用引用计数来跟踪指向同一对象的指针数量。当引用计数减少到零时,`shared_ptr`会自动删除所指向的对象。然而,当两个`shared_ptr`相互引用形成循环引用时,它们的...
- `auto_ptr` 是在C++98标准中引入的,但在C++11之后被废弃。它的设计理念是实现所有权转移,即一个`auto_ptr`实例拥有对动态分配对象的所有权,当`auto_ptr`对象离开作用域时,它会自动删除所指向的对象。然而,`...
本文将详细介绍C++中的三种主要智能指针:`auto_ptr`、`unique_ptr`(C++11引入)和`shared_ptr`(C++11引入),以及它们的基本用法和注意事项。 1. `auto_ptr` `auto_ptr`是STL中最早提供的智能指针,它具有独占...
本篇文章将探讨C++11之前的`auto_ptr`以及C++11引入的`unique_ptr`、`shared_ptr`和`weak_ptr`。 首先,让我们看看`auto_ptr`。`auto_ptr`是C++98标准库中的一个智能指针,它使用模板定义,可以自动删除所指向的...
C++标准库提供了四种类型的智能指针,分别是`auto_ptr`(已被弃用),`unique_ptr`,`shared_ptr`和`weak_ptr`。 1. `auto_ptr`: `auto_ptr`是C++98引入的,但在C++11中被弃用,因为它存在安全性问题。`auto_ptr`...