C/C++——跟我重写智能指针auto_ptr模版类

第一次使用auto_ptr的时候感觉很好用,但是对内部原理根本不懂,心里不知道这东西到底是个什么东东,总是感觉这东东比较陌生。今天有时间来简单实现一下该类模版auto_ptr,实现了该模版类的主要功能,可以让大家了解一下这个东东内部到底是个什么情况。

栈对象和堆对象的区别:

首先,看一下两种类对象的区别,一个是在栈上分配空间,另一个是在堆上分配空间。

如果看到这里,你不清楚堆和栈的区别。那我也不解释了,自行Google..(如果你想baidu也不拦你)

1、先测试栈上分配的对象

#include <iostream>
#include <memory>
using namespace std;

/****************************************
*   类名称:A(用于测试的类)
****************************************/
class A
{
public:
    A(int num):a(num){cout << "A(int num)" << endl;}
    A(){cout << "A()" << endl;}
    ~A(){cout << "~A()" << endl;}

    void func(){
        cout << "A.fun()" << endl;
    }

private:
    int a;
};

/****************************************
*  主测试函数main
****************************************/
int main()
{
    A a1;
    a1.func();

    //A * pa = new A();
    //pa->func();

    return 0;
}

程序输出为:

A()
A.fun()
~A()

从输出结果可以看出,在栈上分配的对象在离开作用域的时候会自动调用析构函数,不用手动释放。

2、再测试堆上分配的对象

将上面的main函数改为下面:

/****************************************
*  主测试函数main
****************************************/
int main()
{
    //A a1;
    //a1.func();

    A * pa = new A();
    pa->func();

    return 0;
}

程序输出为:

A()
A.fun()

从输出结果可以看出,在堆上分配的对象在离开作用域的时候不会自动调用析构函数,需要手动释放。

下面是添加手动释放对象的语句:

/****************************************
*  主测试函数main
****************************************/
int main()
{
    //A a1;
    //a1.func();

    A * pa = new A();
    pa->func();
    delete pa;

    return 0;
}

下面是改了之后的程序输出:

A()
A.fun()
~A()

为什么需要智能指针?

从上面的例子可以看出,对于在堆上分配的对象的释放是一件比较麻烦的事情,如果忘了手动释放,那就会造成内存的泄漏。如果全部收到释放,那么又给程序员带来很大的麻烦。

那么就想啊,有什么办法可以像栈对象那样操作堆对象。栈对象是在栈内存空间的对象,当对象超过作用域的时候会自动释放。那么我们可以让栈内存空间上的一个指针对象专门来管理堆对象,当指针对象离开作用域的时候肯定会调用自身的析构函数,那么我们在指针对象的析构函数中对它管理的堆对象内存空间进行释放。

智能指针auto_ptr简单应用实例:

#include <iostream>
#include <memory>
using namespace std;

/****************************************
*   类名称:A(用于测试的类)
****************************************/
class A
{
public:
    A(int num):a(num){cout << "A(int num)" << endl;}
    A(){cout << "A()" << endl;}
    ~A(){cout << "~A()" << endl;}

    void func(){
        cout << "A.fun()" << endl;
    }

private:
    int a;
};

/****************************************
*  主测试函数main
****************************************/
int main()
{
    //使用智能指针模版类auto_ptr
    //new A等价于new A(),但是如果有括号的话,可以调用带参的构造函数,如new A(10);
    auto_ptr<A> ptr(new A);
    ptr->func();
    (*ptr).func();

    return 0;
}

程序输出为:

A()
A.fun()
A.fun()
~A()

在上面的例子中可以看出,auto_ptr是一个模版类,我们在这里定义了一个管理类A对象的一个指针对象ptr,该指针对象ptr可以使用运算符->和*,所以在类auto_ptr中重载了运算符->和*。

在上面例子中的指针对象ptr是栈对象,在离开作用域的时候会自动释放,然后会自动调用析构函数,在它的析构函数中会释放它指向的堆对象,从而达到了智能指针的效果。

重写智能指针模版类SmartPointer:

/****************************************
*   类名称:Smart智能指针模版类
****************************************/

template<typename T>
class SmartPointer
{
public:
    //构造函数
    SmartPointer(T * p = NULL):ptr(p){

    }

    //析构函数
    ~SmartPointer(){
        if(ptr != NULL)
            delete ptr;
    }

    //重载->运算符
    T * operator->(){
        return ptr;
    }

    //重载*运算符
    T & operator*(){
        return *ptr;
    }
private:
    T * ptr;
};

在程序中可以看出,该模版类重载了运算符->和*,并实现了管理堆对象的功能。

下面是测试智能指针模版类SmartPointer:

/*************************************************************************
	> File Name: smartPointerTemplate.cpp
	> Author:
	> Mail:
	> Created Time: 2016年05月10日 星期二 19时26分14秒
 ************************************************************************/

#include <iostream>
using namespace std;

/****************************************
*   类名称:A(用于测试的类)
****************************************/
class A
{
public:
    A(int num):a(num){cout << "A(int num)" << endl;}
    A(){cout << "A()" << endl;}
    ~A(){cout << "~A()" << endl;}

    void func(){
        cout << "A::fun()" << endl;
    }

private:
    int a;
};

/****************************************
*   类名称:B(用于测试的类)
****************************************/
class B
{
public:
    B(){cout << "B()" << endl;}
    ~B(){cout << "~B()" << endl;}

    void func(){
        cout << "B::func()" << endl;
    }

};

/****************************************
*   类名称:Smart智能指针模版类
****************************************/

template<typename T>
class SmartPointer
{
public:
    //构造函数
    SmartPointer(T * p = NULL):ptr(p){

    }

    //析构函数
    ~SmartPointer(){
        if(ptr != NULL)
            delete ptr;
    }

    //重载->运算符
    T * operator->(){
        return ptr;
    }

    //重载*运算符
    T & operator*(){
        return *ptr;
    }
private:
    T * ptr;
};

/****************************************
*  主测试函数main
****************************************/
int main()
{
    SmartPointer<A> smt(new A());
    smt->func();
    (*smt).func();

    SmartPointer<B> smtB(new B());
    smtB->func();
    (*smtB).func();

    return 0;
}

下面是程序的输出结果:

A()
A::fun()
A::fun()
B()
B::func()
B::func()
~B()
~A()

从输出结果可以看出该模版类智能指针也实现了管理堆对象的功能。

时间: 2024-10-22 14:58:17

C/C++——跟我重写智能指针auto_ptr模版类的相关文章

智能指针auto_ptr详解

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

C++中的智能指针(auto_ptr)

实际上auto_ptr 只是C++标准库提供的一个类模板,它与传统的new/delete控制内存相比有一定优势,使用它不必每次都手动调用delete去释放内存.当然有利也有弊,也不是完全完美的. 本文从下面的8个方面来总结auto_ptr使用的大部分内容. 1. auto_ptr是什么? auto_ptr 是C++标准库提供的类模板,auto_ptr对象通过初始化指向由new创建的动态内存,它是这块内存的拥有者,一块内存不能同时被分给两个这样拥有者(auto_ptr).当auto_ptr对象生命

C++:浅谈c++资源管理以及对[STL]智能指针auto_ptr源码分析,左值与右值

C++:浅谈c++资源管理以及对[STL]智能指针auto_ptr源码分析 by 小威威 1. 知识引入 在C++编程中,动态分配的内存在使用完毕之后一般都要delete(释放),否则就会造成内存泄漏,导致不必要的后果.虽然大多数初学者都会有这样的意识,但是有些却不以为意.我曾问我的同学关于动态内存的分配与释放,他的回答是:"只要保证new和delete成对出现就行了.如果在构造函数中new(动态分配内存),那么在析构函数中delete(释放)就可以避免内存泄漏了!" 事实果真如此么?

【C++智能指针 auto_ptr】

<More Effective C++>ITEM M9中提到了auto_ptr,说是当异常产生的时候,怎么释放为对象分配的堆内存,避免重复编写内存释放语句. PS:这里书里面提到函数退出问题,函数退出会清理栈内存,不管是怎么正常退出还是异常退出(仅有一种例外就是当你调用 longjmp 时.Longjmp 的这个缺点是 C++率先支持异常处理的主要原因).建立在此基础上我们才把对指针的删除操作封装到一个栈对象里面.这样函数退出(异常或是正常)就会调用对象的析构函数,达到我们自动清理所封装指针指

C++智能指针 auto_ptr

C++智能指针 auto_ptr auto_ptr 是一个轻量级的智能指针, 定义于 memory (非memory.h)中, 命名空间为 std. auto_ptr 适合用来管理生命周期比较短或者不会被远距离传递的动态对象, 最好是局限于某个函数内部或者是某个类的内部. 使用方法: std::auto_ptr<int> pt(new int(10)); pt.reset(new int(11)); 成员函数 3个重要的函数: (1) get 获得内部对象的指针, 由于已经重载了()方法, 因

C++智能指针--auto_ptr指针

auto_ptr是C++标准库提供的类模板,头文件<memory>,auto_ptr对象通过初始化指向由new创建的动态内存,它是这块内存的拥有者,一块内存不能同时被分给两个拥有者.当auto_ptr对象生命周期结束时,其析构函数会将auto_ptr对象拥有的动态内存自动释放.即使发生异常,通过异常的栈展开过程也能将动态内存释放.auto_ptr不支持new数组. auto_ptr的出现,主要是为了解决"有异常抛出时发生内存泄漏"的问题.如下的简单代码是这类问题的一个简单示

C++ 智能指针auto_ptr详解

1. auto_ptr 的设计动机: 函数操作经常依照下列模式进行: 获取一些资源 执行一些动作 释放所获取的资源 那么面对这些资源的释放问题就会出现下面的两种情况: 一开始获得的资源被绑定于局部对象,那么当函数退出的时候,这些局部对象的析构函数被自动的调用,从而自动释放掉这些资源; 一开始获得的资源是通过某种显示手段获取,而且并没有绑定在任何对象身上,那么必须以显式的方式释放.这种情况常常发生在指针身上; 例子: 1 void f() 2 { 3 ClassA* ptr = new Class

【C++】智能指针auto_ptr的简单实现

//[C++]智能指针auto_ptr的简单实现 #include <iostream> using namespace std; template <class _Ty> class auto_ptr { public: auto_ptr(_Ty *_P = 0) :_Owns(_Ptr != 0), _Ptr(_P) {} auto_ptr<_Ty>(const auto_ptr <_Ty> &p):_Owns(p._Owns),_Ptr(p.r

智能指针auto_ptr源码剖析

何时我们需要智能指针? 资源所有权的共享 共享所有权是指两个或多个对象需要同时使用第三个对象的情况.这第三个对象应该如何(或者说何时)被释放?为了确保释放的时机是正确的,每个使用这个共享资源的对象必须互相知道对方,才能准确掌握资源的释放时间.从设计或维护的观点来看,这种耦合是不可行的.更好的方法是让这些资源所有者将资源的生存期管理责任委派给一个智能指针.当没有共享者存在时,智能指针就可以安全地释放这个资源了. 要编写异常安全的代码时 异常安全简单地说就是在异常抛出时没有资源泄漏并保证程序状态的一