C++智能指针,指针容器原理及简单实现(auto_ptr,scoped_ptr,ptr_vector).

目录

  • C++智能指针,指针容器原理及简单实现(auto_ptr,scoped_ptr,ptr_vector).
  • auto_ptr
  • scoped_ptr
  • ptr_vector

C++智能指针,指针容器原理及简单实现(auto_ptr,scoped_ptr,ptr_vector).


前言

最近再写一个muduo的异步日志接触了很多智能指针,但是又不打算用boost库,只好模一个来用用了.

智能指针的本质即用栈上对象来管理堆上数据的生命周期.

智能指针本身是一个对象,它在栈上创建,构造的时候分配堆上资源,析构的时候释放资源,这样就避免了堆上数据资源泄露的情况.

同时重载它的-> 和 * 运算符实现如同裸指针一样的操作.

下面看看几个局部智能指针对象的实现代码。

auto_ptr

auto_ptr特点: 实现拷贝构造函数, 重载 = 运算符, 实现->、* 运算符, 使它能够像普通指针一样 使用,

同时通过release() 和 reset() 方法实现安全的转移使用权 .

#ifndef _AUTO_PTR_HH
#define _AUTO_PTR_HH

template<typename T>
class auto_ptr{
public:
    explicit auto_ptr(T* p = 0):m_ptr(p){printf("1\n");
    }

    auto_ptr(auto_ptr& obj):m_ptr(obj.release()){printf("2\n");
    }

    auto_ptr& operator=(auto_ptr& obj){printf("3\n");
        reset(obj.release());
        return *this;
    }

    ~auto_ptr(){printf("4\n");
        delete m_ptr;
    }

    T* release(){
        T* tmp = m_ptr;
        m_ptr = 0;
        return tmp;
    }

    void reset(T* p){
        if(m_ptr != p)
            delete m_ptr;
        m_ptr = p;
    }

    T* get() const {
        return m_ptr;
    }

    T* operator->(){
        return get();
    }

    T& operator*(){
        return *get();
    }

private:
    T* m_ptr;
};

#endif

测试代码:

#include "ScopePtr.hh"
#include "auto_ptr.hh"
#include <stdio.h>

class NonCopyable
{
protected: //构造函数可以被派生类调用,但不能直接构造对象
    NonCopyable() {printf("Nocopy Constroctr\n");}
    ~NonCopyable() {printf("~Nocopy DeConstroctr\n");}
private:
    NonCopyable(const NonCopyable &);
    const NonCopyable &operator=(const NonCopyable &);
};

class Test// : private NonCopyable{
{public:
    Test(){printf("Constroctr\n");}
    ~Test(){printf("~DeConstroctr\n");}
};

int main(){

    //scoped_ptr<Test> st(new Test);

    auto_ptr<Test> ap1(new Test);
    auto_ptr<Test> ap2(new Test);

    auto_ptr<Test> ap3(ap2);

    ap2 = ap3;

    getchar();
    return 0;
}

Constroctr
1
Constroctr
1
2
3

4
4
~DeConstroctr
4
~DeConstroctr

scoped_ptr

这个是boost库里面的东西,它和auto_ptr正相反: 将拷贝构造和=重载 都配置为私有,已达到不允许转移拥有权的目的.

#ifndef _SCOPE_PTR_HH
#define _SCOPE_PTR_HH
//  scoped_ptr mimics a built-in pointer except that it guarantees deletion
//  of the object pointed to, either on destruction of the scoped_ptr or via
//  an explicit reset(). scoped_ptr is a simple solution for simple needs;
//  use shared_ptr or std::auto_ptr if your needs are more complex.

/*
scoped_ptr 是局部智能指针 不允许转让所有权。
*/
template <class T>
class scoped_ptr
{
public:
    scoped_ptr(T *p = 0) :m_ptr(p) {
    }

    ~scoped_ptr(){
        delete m_ptr;
    }

    T&operator*() const {
        return *m_ptr;
    }

    T*operator->() const {
        return m_ptr;
    }

    void reset(T *p)//拥有权不允许转让  但是可以让智能指针指向另一个空间
    {
        if (p != m_ptr && m_ptr != 0)
            delete m_ptr;
        m_ptr = p;
    }

    T* get(){
        return m_ptr;
    }

private://将拷贝构造和赋值  以及判等判不等  都设置为私有方法
    //对象不再能调用,即不能拷贝构造和赋值  也就达到了不让转移拥有权的目的
    scoped_ptr(const scoped_ptr<T> &y);
    scoped_ptr<T> operator=(const scoped_ptr<T> &);
    void operator==(scoped_ptr<T> const &) const;
    void operator!=(scoped_ptr<T> const &) const;

    T* m_ptr;
};

#endif

ptr_vector

这个也是boost里面的东西,如果我们光放对象指针到vector里面,容器析构的时候虽然会析构自己开辟出来的存放指针的空间,但不会析构指针本身指向的空间,于是有了这个容器.

#ifndef _PTR_VECTOR_HH
#define _PTR_VECTOR_HH

#include "auto_ptr.hh"
#include <vector>

template<typename T>
class ptr_vector : public std::vector<T*>{
public:
    ~ptr_vector(){
        clear();
    }

    void clear(){
        typename std::vector<T*>::iterator it;
        for(it = std::vector<T*>::begin(); it != std::vector<T*>::end(); ++it){
            delete *it;//释放指针指向的内存.
        }

        /*
        for(size_t i = 0; i < std::vector<T*>::size(); ++i){
            delete std::vector<T*>::back();
        }*/

        std::vector<T*>::clear(); //释放指针本身.
    }

    typename std::vector<T*>::iterator erase(typename std::vector<T*>::iterator it){
        if(it >= std::vector<T*>::begin() && it < std::vector<T*>::end()){
            delete *it;
            std::vector<T*>::erase(it);
        }
    }

    void pop_back(){
        if(std::vector<T*>::size() > 0){
            delete std::vector<T*>::back();
            std::vector<T*>::pop_back();
        }
    }

    void push_back(T* const &v){
        auto_ptr<T> ap(v);
        std::vector<T*>::push_back(v);
        ap.release();
    }

    void push_back(auto_ptr<T> &v){
        std::vector<T*>::push_back(v.get());
        v.release();
    }

};

#endif

测试代码:


class Test// : private NonCopyable{
{public:
    Test(int a = 99):a(a){printf("Constroctr\n");}
    ~Test(){printf("~DeConstroctr\n");}
    int get(){return a;}
private:
    int a;
};

int main(){
    auto_ptr<Test> ap1(new Test(0));
    auto_ptr<Test> ap2(new Test(1));
    auto_ptr<Test> ap3(new Test(2));

    printf("%d\n", ap1->get());

    ptr_vector<Test> apv;
    apv.push_back(ap1);
    apv.push_back(ap2);
    apv.push_back(ap3);
    printf("%d %lu \n", apv.front()->get(),apv.size());
/*
    apv.pop_back();
    printf("%lu\n", apv.size());

    apv.pop_back();
    printf("%lu\n", apv.size());

    apv.pop_back();
    printf("%lu\n", apv.size());
*/
    apv.pop_back();
    printf("%lu\n", apv.size());

    ptr_vector<Test>::iterator it = apv.begin();
    apv.erase(it);
    printf("%lu\n", apv.size());

    getchar();

    return 0;
}

Constroctr
Constroctr
Constroctr
0
0 3
~DeConstroctr
2
~DeConstroctr
1

~DeConstroctr

本文主介绍了智能指针的本质,及两种简单的智能指针实现与一个指针容器的实现.

事实上现在auto_ptr用的不多,如果没对原来传进来的指针进行处理,转移后,原来的指针为空了,如果有人去使用既会造成问题。

vector也存在很多问题,pop_back()一个空的容器,vector里面照样会做--size,这时候容器大小从0就变成了无限大,后果无法预料,.本例中对这种情况进行了处理. pop_back()一个空的vector将什么都不做. 但是vector用法还是有讲究的,不然容易造成问题.

原文地址:https://www.cnblogs.com/ailumiyana/p/9451761.html

时间: 2024-08-29 06:46:35

C++智能指针,指针容器原理及简单实现(auto_ptr,scoped_ptr,ptr_vector).的相关文章

智能指针原理与简单实现(转)

以下实现没有考虑线程安全的问题. 智能指针:它的一种通用实现方法是采用引用计数的方法.智能指针将一个计数器与类指向的对象相关联,引用计数跟踪共有多少个类对象共享同一指针. 每次创建类的新对象时,初始化指针并将引用计数置为1: 当对象作为另一对象的副本而创建时,拷贝构造函数拷贝指针并增加与之相应的引用计数: 对一个对象进行赋值时,赋值操作符减少左操作数所指对象的引用计数(如果引用计数为减至0,则删除对象),并增加右操作数所指对象的引用计数:这是因此左侧的指针指向了右侧指针所指向的对象,因此右指针所

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

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

Windows-消息映射机制原理和简单的绘图技术

Windows-消息映射机制原理和简单的绘图技术 1.MFC消息映射机制 众所周知,Windows程序是基于消息编程的,但是在MFC中已经为我们封装好了这个框架的消息机制,我们需要了解它的实现原理,才能深入的学习和精通Visual C++. **(1).消息映射机制的原理: MFC消息映射机制的具体实现方法是,在每个能接收和处理消息的类中,定义一个消息和消息函数静态对照表,即消息映射表.在消息映射表中,消息与对应的消息处理函数指针是成对出现的.某个类能处理的所有消息及其对应的消息处理函数的地址都

深入理解指针—&gt;指针函数与函数指针的区别

一. 在学习过程中发现这"指针函数"与"函数指针"容易搞错,所以今天,我自己想一次把它搞清楚,找了一些资料,首先它们之间的定义: 1.指针函数是指带指针的函数,即本质是一个函数.函数返回类型是某一类型的指针 类型标识符    *函数名(参数表) int *f(x,y); 首先它是一个函数,只不过这个函数的返回值是一个地址值.函数返回值必须用同类型的指针变量来接受,也就是说,指针函数一定有函数返回值,而且,在主调函数中,函数返回值必须赋给同类型的指针变量. 表示: f

菜鸟学SSH(十三)——Spring容器解析及简单实现

最近一段时间,"容器"两个字一直萦绕在我的耳边,甚至是吃饭.睡觉的时候都在我脑子里蹦来蹦去的.随着这些天一次次的交流.讨论,对于容器的理解也逐渐加深.理论上的东西终归要落实到实践,今天就借助Spring容器实现原理,简单说说吧. 简单的说,Spring就是通过工厂+反射将我们的bean放到它的容器中的,当我们想用某个bean的时候,只需要调用getBean("beanID")方法. 原理简单介绍: Spring容器的原理,其实就是通过解析xml文件,或取到用户配置的

spring容器原理一

spring IOC使应用中依赖管理变得简单,所以的bean创建,以及当前bean所需要的另外类的实例都由容器来管理. 想像下,如果不用spring ioc.有业务类A,需要业务类B的实例.而业务类B需要业务类C的实例.这里如果业务类A为入口main方法,我们需要进行以下几个步聚完成A类的实例化: 1.手动创建C类实例 2.然后创建B类实例并将之前创建的C类实例插入到B的字段中 3.最后创建A的实例,并将B的实例插入到A类的字段中 可以想像实例化,并管理这些依赖的过程对于程序员来说,简直是灾难.

C语言基础知识----指针数组 &amp;&amp; 数组指针 &amp;&amp; 函数指针 &amp;&amp;指针函数

指针数组 && 数组指针 char (*ptr)[5]; //定义一个指向数组指针ptr,指向包含5个char类型的数组 char *a[5]; //定义一个指针数组a,包含5个char*类型指针 #include <stdio.h> int main(void) {     char *a[5]={"red","white","blue","dark","green"};   

常见指针:指针函数 函数指针 指针的指针 指向指针数组的指针

一.指针函数与函数指针 在学习arm过程中发现这“指针函数”与“函数指针”容易搞错,所以今天,我自己想一次把它搞清楚,找了一些资料,首先它们之间的定义: 1.指针函数是指带指针的函数,即本质是一个函数.函数返回类型是某一类型的指针 类型标识符    *函数名(参数表) int *f(x,y); 首先它是一个函数,只不过这个函数的返回值是一个地址值.函数返回值必须用同类型的指针变量来接受,也就是说,指针函数一定有函数返回值,而且,在主调函数中,函数返回值必须赋给同类型的指针变量. 表示: floa

【C/C++学院】0726-cppIDE/一级指针/指针数组/函数指针/函数指针数组/二级指针

[送给在路上的程序员] 对于一个开发者而言,能够胜任系统中任意一个模块的开发是其核心价值的体现. 对于一个架构师而言,掌握各种语言的优势并可以运用到系统中,由此简化系统的开发,是其架构生涯的第一步. 对于一个开发团队而言,能在短期内开发出用户满意的软件系统是起核心竞争力的体现. 每一个程序员都不能固步自封,要多接触新的行业,新的技术领域,突破自我. cppIDE 使用mfc和codeblocks中的mingw编译器.执行system命令中的bat批处理脚本. 一级指针 指针,结构体struct,