C++智能指针之auto_ptr

1. auto_ptr

auto_ptr 是C++标准库提供的类模板,auto_ptr对象通过初始化指向由new创建的动态内存,它是这块内存的拥有者,一块内存不能同时被分给两个拥有者。当auto_ptr对象生命周期结束时,其析构函数会将auto_ptr对象拥有的动态内存自动释放。即使发生异常,通过异常的栈展开过程也能将动态内存释放。auto_ptr不支持new
数组。

2. auto_ptr需要包含的头文件

#include <memory>

3. 初始化auto_ptr对象的方法

1) 构造函数

1] 将已存在的指向动态内存的普通指针作为参数来构造

int* p = new int(33);

auto_ptr<int> api(p);

2] 直接构造智能指针

auto_ptr< int > api( new int( 33 ) );

2) 拷贝构造

利用已经存在的智能指针来构造新的智能指针

auto_ptr< string > pstr_auto( new string( "Brontosaurus" ) );

auto_ptr< string > pstr_auto2( pstr_auto );  //利用pstr_auto来构造pstr_auto2

因为一块动态内存智能由一个智能指针独享,所以在拷贝构造或赋值时都会发生拥有权转移的过程。

在此拷贝构造过程中,pstr_auto将失去对字符串内存的所有权,而pstr_auto2将其获得;对象销毁时,pstr_auto2负责内存的自动销毁。

3) 赋值

利用已经存在的智能指针来构造新的智能指针

auto_ptr< int > p1( new int( 1024 ) );

auto_ptr< int > p2( new int( 2048 ) );

p1 = p2;

在赋值之前,由p1 指向的对象被删除。赋值之后,p1 拥有int 型对象的所有权。该对象值为2048。 p2 不再被用来指向该对象。

4. 空的auto_ptr

通常的指针在定义的时候若不指向任何对象,我们用Null给其赋值。对于智能指针,因为构造函数有默认值0,我们可以直接定义空的auto_ptr如下:

auto_ptr< int > p_auto_int;  //不指向任何对象

5. 防止两个auto_ptr对象拥有同一个对象(一块内存)

因为auto_ptr的所有权独有,所以下面的代码会造成混乱。

int* p = new int(0);

auto_ptr<int> ap1(p);

auto_ptr<int> ap2(p);

因为ap1与ap2都认为指针p是归它管的,在析构时都试图删除p, 两次删除同一个对象的行为在C++标准中是未定义的;所以我们必须防止这样使用auto_ptr。

6. 警惕智能指针作为参数

1) 按值传递时,函数调用过程中在函数的作用域中会产生一个局部对象来接收传入的auto_ptr(拷贝构造),这样,传入的实参auto_ptr就失去了其对原对象的所有权,而该对象会在函数退出时被局部auto_ptr删除。如下例:

void f(auto_ptr<int> ap)

{cout<<*ap;}

auto_ptr<int> ap1(new int(0));

f(ap1);

cout<<*ap1; //错误,经过f(ap1)函数调用,ap1已经不再拥有任何对象了。

2) 引用或指针时,不会存在上面的拷贝过程。但我们并不知道在函数中对传入的auto_ptr做了什么,如果当中某些操作使其失去了对对象的所有权,那么这还是可能会导致致命的执行期错误。

结论:const reference是智能指针作为参数传递的底线

7. auto_ptr不能初始化为指向非动态内存

原因很简单,delete 表达式会被应用在不是动态分配的指针上这将导致未定义的程序行为。

8. auto_ptr常用的成员函数

1) get()

返回auto_ptr指向的那个对象的内存地址。如下例:

int* p = new int(33);

cout << "the adress of p: "<< p << endl;

auto_ptr<int> ap1(p);

cout << "the adress of ap1: " << &ap1 << endl;

cout << "the adress of the object which ap1 point to: " << ap1.get() << endl;

输出如下:

the adress of p: 00481E00

the adress of ap1: 0012FF68

the adress of the object which ap1 point to: 00481E00

第一行与第三行相同,都是int所在的那块内存的地址。第二行是ap1这个类对象本身所在内存的地址。

2) reset()

重新设置auto_ptr指向的对象。类似于赋值操作,但赋值操作不允许将一个普通指针指直接赋给auto_ptr,而reset()允许。如下例:

auto_ptr< string > pstr_auto( new string( "Brontosaurus" ) );

pstr_auto.reset( new string( "Long -neck" ) );

在例子中,重置前pstr_auto拥有"Brontosaurus"字符内存的所有权,这块内存首先会被释放。之后pstr_auto再拥有"Long -neck"字符内存的所有权。

注:reset(0)可以释放对象,销毁内存。

3) release()

返回auto_ptr指向的那个对象的内存地址,并释放对这个对象的所有权。

用此函数初始化auto_ptr时可以避免两个auto_ptr对象拥有同一个对象的情况(与get函数相比)。

例子如下:

auto_ptr< string > pstr_auto( new string( "Brontosaurus" ) );

auto_ptr< string > pstr_auto2( pstr_auto.get() ); //这是两个auto_ptr拥有同一个对象,在释放对象时,会出现未定义行为

auto_ptr< string > pstr_auto2( pstr_auto.release() ); //release可以首先释放所有权

示例

#include <iostream>
#include <memory>

using namespace std;

struct A
{
        explicit A(string str){m_str = str; cout << m_str << " : constructor~~" << endl; }
        ~A(){cout << m_str << " : deconstructor~~~" << endl;}
        void outmsg(){cout << "outmsg : "+m_str << endl;}
        private:
        string m_str;
};
int main()
{
        auto_ptr<A> aptr (new A(string("auto")));
        aptr.get()->outmsg();
        aptr.reset(new A(string("msg")));
        auto_ptr<A> aptr2 (aptr.release());
        //auto_ptr<A> aptr2 (aptr.get());  //出现段错误,这是由于aptr和aptr2指向了同一个对象,出现了重复释放的问题  double free or corruption (fasttop)
}

执行结果:

auto : constructor~~

outmsg : auto

msg : constructor~~

auto : deconstructor~~~

msg : deconstructor~~~

时间: 2024-11-05 12:16:55

C++智能指针之auto_ptr的相关文章

【C++深入浅出】智能指针之auto_ptr学习

起:  C++98标准加入auto_ptr,即智能指针,C++11加入shared_ptr和weak_ptr两种智能指针,先从auto_ptr的定义学习一下auto_ptr的用法. template<class _Ty> class auto_ptr { // wrap an object pointer to ensure destruction public: //定义_Myt类型,作用域局限于类中,便于书写和理解 typedef auto_ptr<_Ty> _Myt; typ

(转)剖析C++标准库智能指针(std::auto_ptr)

不可否认,资源泄露(resource leak)曾经是C++程序的一大噩梦.垃圾回收 机制(Garbage Collection)一时颇受注目.然而垃圾自动回收机制并不能 满足内存管理的即时性和可视性,往往使高傲的程序设计者感到不自在. 况且,C++实现没有引入这种机制.在探索中,C++程序员创造了锋利的 "Smart Pointer".一定程度上,解决了资源泄露问题. 也许,经常的,你会写这样的代码: //x拟为class: // class x{ // public: // int

智能指针 std::auto_ptr 和 shared_ptr

需要注意: auto_ptr 类可以用于管理由 new 分配的单个对象,但是无法管理动态分配的数组(我们通常不会使用数组,而是使用 vector 代替数组).auto_ptr 在拷贝和赋值的时候有不寻常的行为,因此 auto_ptrs 不能被保存在 stl 的容器中.当 auto_ptr 离开了自己的作用域或者被销毁,由 auto_ptr 管理的对象也会被销毁. 使用std::auto_ptr需要的头文件: #include <memory> // 示例 1(b): 安全代码, 使用了auto

四种智能指针:auto_ptr,unique_ptr,shared_ptr,weak_ptr

stl中auto_ptr,unique_ptr,shared_ptr,weak_ptr四种智能指针的使用总结 (1)auto_ptr 主要用于解决资源自动释放的问题.防止用户忘记delete掉new申请的内存空间.使用auto_ptr会在离开变量的作用域之后直接调用析构函数进行资源释放. void Function() { auto_ptr<Obj> ptr(new Obj(20)); ... if (error occur) throw exception... } 但是,这是一种被c++1

智能指针之 auto_ptr

C++的auto_ptr所做的事情,就是动态分配对象以及当对象不再需要时自动执行清理,该智能指针在C++11中已经被弃用,转而由unique_ptr替代, 那这次使用和实现,就具体讲一下auto_ptr被弃用的原因,(编译平台:Linux centos 7.0 编译器:gcc 4.8.5 ) 首先使用std::auto_ptr时,需要#include <memory>头文件,具体使用代码如下(文件名:test_ptr.cpp): #include <memory> #include

智能指针之auto_ptr和scoped_ptr

部分参考地址https://blog.csdn.net/yanglingwell/article/details/56011576 auto_ptr是c++标准库里的智能指针,但是具有以下几个明显的缺陷,使用时要注意 1.就是所谓的控制权转移,下面是模拟代码 auto_Ptr(auto_Ptr<T>&ap) { _ptr = new T; //先分配空间 _ptr = ap._ptr; //再资源转移 ap._ptr = NULL; //将原来的指针置空 } 在赋值运算符重载和拷贝构造

智能指针(auto_ptr)vc版

auto_ptr包含于头文件 #include<memory> 其中<vector><string>这些库中也存有.auto_ptr 能够方便的管理单个堆内存对象,在你不用的时候自动帮你释放内存. auto_ptr的设计目的: 局部对象获取的资源(内存),当函数退出时,它们的析构函数被调用,从而自动释放这些资源,但是,如果以显式手法获得的资源(称为动态分配内存空间如:new.malloc等)没有绑定在任何对象身上,必须以显式手法释放.(如:delete,free等).

智能指针的模拟实现 auto_ptr scoped_ptr shared_ptr

RAII(Resource Acquisition Is Initialization) 资源分配即初始化,定义一个类来封装资源的分配和释放,在构造函数完成资源的分配和初始化,在析构函数完成资源的清理,可以保证资源的正确初始化和释放. 智能指针:用自动化或者说智能的指针来实现对动态内存的释放.它是一个类,有类似指针的功能. 常见的智能指针:auto_ptr/scoped_ptr/scoped_array/shared_ptr/shared_array,由于scoped_array和scoped_

智能指针auto_ptr详解

概述:C++中有很多种智能指针,auto_ptr就是其中的一种,该智能指针主要是为了解决"因程序异常退出发生的内存泄漏"这类问题的. 我们先来看下面的问题代码 #include<iostream> #include<memory> #include<exception> using namespace std; //一般指针的处理方式 template<typename T> class OldClass { public: OldCla