STL auto_ptr

先贴下auto_ptr的SGI实现

/*
 * Copyright (c) 1997-1999
 * Silicon Graphics Computer Systems, Inc.
 *
 * Permission to use, copy, modify, distribute and sell this software
 * and its documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  Silicon Graphics makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 *
 */

#ifndef __SGI_STL_MEMORY
#define __SGI_STL_MEMORY

#include <stl_algobase.h>
#include <stl_alloc.h>
#include <stl_construct.h>
#include <stl_tempbuf.h>
#include <stl_uninitialized.h>
#include <stl_raw_storage_iter.h>


__STL_BEGIN_NAMESPACE

#if defined(__SGI_STL_USE_AUTO_PTR_CONVERSIONS) && \
    defined(__STL_MEMBER_TEMPLATES)

template<class _Tp1> struct auto_ptr_ref {
  _Tp1* _M_ptr;
  auto_ptr_ref(_Tp1* __p) : _M_ptr(__p) {}
};

#endif

template <class _Tp> class auto_ptr {
private:
  _Tp* _M_ptr;

public:
  typedef _Tp element_type;

  explicit auto_ptr(_Tp* __p = 0) __STL_NOTHROW : _M_ptr(__p) {}
  auto_ptr(auto_ptr& __a) __STL_NOTHROW : _M_ptr(__a.release()) {}

#ifdef __STL_MEMBER_TEMPLATES
  template <class _Tp1> auto_ptr(auto_ptr<_Tp1>& __a) __STL_NOTHROW
    : _M_ptr(__a.release()) {}
#endif /* __STL_MEMBER_TEMPLATES */

  auto_ptr& operator=(auto_ptr& __a) __STL_NOTHROW {
    if (&__a != this) {
      delete _M_ptr;
      _M_ptr = __a.release();
    }
    return *this;
  }

#ifdef __STL_MEMBER_TEMPLATES
  template <class _Tp1>
  auto_ptr& operator=(auto_ptr<_Tp1>& __a) __STL_NOTHROW {
    if (__a.get() != this->get()) {
      delete _M_ptr;
      _M_ptr = __a.release();
    }
    return *this;
  }
#endif /* __STL_MEMBER_TEMPLATES */

  // Note: 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 (17.4.3.6/2)
  // this is prohibited.
  ~auto_ptr() { delete _M_ptr; }

  _Tp& operator*() const __STL_NOTHROW {
    return *_M_ptr;
  }
  _Tp* operator->() const __STL_NOTHROW {
    return _M_ptr;
  }
  _Tp* get() const __STL_NOTHROW {
    return _M_ptr;
  }
  _Tp* release() __STL_NOTHROW {
    _Tp* __tmp = _M_ptr;
    _M_ptr = 0;
    return __tmp;
  }
  void reset(_Tp* __p = 0) __STL_NOTHROW {
    if (__p != _M_ptr) {
      delete _M_ptr;
      _M_ptr = __p;
    }
  }

  // According to the C++ standard, these conversions are required.  Most
  // present-day compilers, however, do not enforce that requirement---and, 
  // in fact, most present-day compilers do not support the language 
  // features that these conversions rely on.
  
#if defined(__SGI_STL_USE_AUTO_PTR_CONVERSIONS) && \
    defined(__STL_MEMBER_TEMPLATES)

public:
  auto_ptr(auto_ptr_ref<_Tp> __ref) __STL_NOTHROW
    : _M_ptr(__ref._M_ptr) {}

  auto_ptr& operator=(auto_ptr_ref<_Tp> __ref) __STL_NOTHROW {
    if (__ref._M_ptr != this->get()) {
      delete _M_ptr;
      _M_ptr = __ref._M_ptr;
    }
    return *this;
  }

  template <class _Tp1> operator auto_ptr_ref<_Tp1>() __STL_NOTHROW 
    { return auto_ptr_ref<_Tp1>(this->release()); }
  template <class _Tp1> operator auto_ptr<_Tp1>() __STL_NOTHROW
    { return auto_ptr<_Tp1>(this->release()); }

#endif /* auto ptr conversions && member templates */
};

__STL_END_NAMESPACE

#endif /* __SGI_STL_MEMORY */


// Local Variables:
// mode:C++
/

auto_ptr的几个限制:

1、auto_ptr不能共享所有权。 一个指针对象,只能属于一个auto_ptr对象。从源码中的拷贝构造函数和赋值函数可以看出,当用一个auto_ptr的对象ap1去构造或者赋值给另一个auto_ptr的对象ap2时,会先调用ap1.release()。 ap1.release()里面,把_M_ptr置为了0.
2、auto_ptr不能指向数组。从源码可以看出,auto_ptr的析构函数,用的是delete,而不是delete[]
3、auto_ptr不能作为容器的成员。
4、不能通过赋值操作来初始化auto_ptr
std::auto_ptr<int> p(new int(42));     //OK
std::auto_ptr<int> p = new int(42);    //ERROR
这是因为auto_ptr 的构造函数被定义为了explicit

<think>好的,我现在需要回答关于C++中auto_ptr智能指针的使用方法和注意事项。首先,我得回忆一下auto_ptr的基本知识,以及它在C++中的地位。根据提供的引用内容,auto_ptr是C++98引入的智能指针,但现在已被C++11的unique_ptr取代,不过在不支持C++11的环境中可能仍需使用。接下来,我需要整理它的主要用法和需要注意的地方。 首先,auto_ptr的主要用途是管理动态分配的内存,防止内存泄漏。它通过RAII机制,在析构时自动释放所拥有的对象。使用方法方面,用户需要包含头文件<memory>,然后通过构造函数或reset()方法来管理对象。例如,初始化时可以传入new操作符返回的指针,或者用release()来释放所有权,用get()获取原始指针。 然后,注意事项部分。根据引用中的信息,auto_ptr不能共享所有权,这意味着多个auto_ptr指向同一对象会导致未定义行为。此外,它不能用于数组,因为析构时调用的是delete而非delete[]。另外,auto_ptr不能作为容器元素,因为STL容器需要元素可拷贝和赋值,而auto_ptr在赋值时会转移所有权,导致意外行为。还有,避免在全局作用域定义auto_ptr,因为析构顺序可能引发问题。最后,动态分配auto_ptr本身可能有问题,应该避免。 在组织回答时,需要分点清晰,先介绍用法再列出注意事项,并适当引用提供的资料来支持观点。同时,确保使用正确的中文表达,避免技术术语错误。可能还需要比较auto_ptr和其他智能指针如unique_ptr的区别,但由于用户主要问的是auto_ptr,可以简要提及替代方案即可。 需要检查是否覆盖了所有重要的点,比如头文件、构造函数、成员函数如get、release、reset,以及注意事项中的所有权、数组、容器使用等。同时,确保没有遗漏引用中的关键信息,例如auto_ptr在C++11中的替代情况。 最后,生成的相关问题需要围绕auto_ptr的替代、与unique_ptr的区别、内存泄漏示例、传统指针比较以及适用场景展开,确保问题与主题相关且有参考价值。</think>### C++ auto_ptr 智能指针详解 #### 一、auto_ptr 基本用法 1. **头文件引入** 使用前需包含头文件: ```cpp #include <memory> ``` 2. **初始化与赋值** - 通过构造函数直接初始化: ```cpp auto_ptr<int> p1(new int(10)); // 管理动态分配的int ``` - 通过 `reset()` 方法重置管理的对象: ```cpp p1.reset(new int(20)); // 释放原有对象,接管新对象 ``` 3. **关键成员函数** - `get()`:获取原始指针(不释放所有权) ```cpp int* raw_ptr = p1.get(); // 仅获取指针,auto_ptr仍负责释放 ``` - `release()`:释放所有权,返回原始指针 ```cpp int* released_ptr = p1.release(); // auto_ptr不再管理该内存 ``` - `reset()`:释放当前对象并接管新对象(若参数为空则仅释放) ```cpp p1.reset(); // 释放当前对象,置为空 ``` #### 二、注意事项 1. **禁止共享所有权** 多个 `auto_ptr` 指向同一对象会导致重复释放。例如: ```cpp int* p = new int(5); auto_ptr<int> a1(p); auto_ptr<int> a2(p); // 错误!两个auto_ptr试图管理同一内存 ``` 2. **不支持数组** `auto_ptr` 析构时调用 `delete`,而数组需调用 `delete[]`。例如: ```cpp auto_ptr<int[]> arr(new int[10]); // 错误!会导致内存泄漏 ``` 3. **不可用于STL容器** STL容器要求元素支持拷贝和赋值,但 `auto_ptr` 赋值会转移所有权: ```cpp vector<auto_ptr<int>> vec; // 错误!可能导致所有权意外转移 ``` 4. **避免全局定义** 全局 `auto_ptr` 的析构顺序不可控,可能引发访问已释放内存的问题[^4]。 5. **不要动态分配auto_ptr自身** 手动管理 `auto_ptr` 的生命周期会破坏其自动释放机制: ```cpp auto_ptr<int>* ptr = new auto_ptr<int>(new int(10)); // 危险! ``` #### 三、替代方案 - **C++11及以上**:使用 `unique_ptr`(直接替代 `auto_ptr`,支持数组和移动语义)和 `shared_ptr`(共享所有权)[^2]。 - **历史代码兼容**:在不支持C++11的环境中,仍需谨慎使用 `auto_ptr`[^3]。 --- ### 相关问题 1. 为什么C++11推荐用`unique_ptr`替代`auto_ptr`? 2. 如何用`auto_ptr`实现异常安全的资源管理? 3. `auto_ptr`和传统指针相比有哪些优缺点? 4. 如果`auto_ptr`拷贝时发生所有权转移,如何避免空指针访问? 5. 在哪些遗留系统中仍然需要使用`auto_ptr`?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值