• 实现一个简单的智能指针


    // helloworld.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include<iostream>
    using namespace std;
    
    //指针类
    class I_Pointer{
    private:
    	int ref_count;
    	int *p;
    	I_Pointer(int *p): p(p), ref_count(1){}; //构造函数 
    	~I_Pointer(){
    		cout<<"Delete shared pointer"<<endl;
    	}
    friend
    	class Has_Ptr;
    };
    
    //有指针成员的类
    class Has_Ptr{
    private:
    	I_Pointer *ptr; //指针成员
    	//减少引用计数
    	void release_ref_count(){
    		cout<<"release reference count"<<endl;
    		if(--(ptr->ref_count) == 1){
    			free_and_nil();
    		}
    	}
    	//增加引用计数
    	void add_ref(){
    		cout<<"add reference count"<<endl;
    		++(ptr->ref_count);
    	}
    	//指针释放
    	void free_and_nil(){
    		delete ptr;
    		ptr = NULL;
    	}
    
    public:
    	// 带int指针的构造函数
    	Has_Ptr(int *ptr): ptr(new I_Pointer(ptr)) {
    		add_ref();
    	}
    
    	Has_Ptr(){} //默认构造
    
    	Has_Ptr(const Has_Ptr &rhs){ //拷贝构造
    		memcpy(this, &rhs, sizeof(rhs));
    		add_ref();
    	}
    
    	~Has_Ptr(){
    		release_ref_count();
    	}
    
    	//赋值
    	Has_Ptr &operator=(const Has_Ptr &rhs){ 
    		//原来的引用计数减1
    		release_ref_count();
    		memcpy(this, &rhs, sizeof(&rhs));		
    		//新的引用计数加1
    		add_ref();
    		return *this;
    	}
    
    	void set_ptr(int *ptr){
    		if (ptr != (this->ptr->p)){
    			this->ptr->p = ptr;
    		}
    	}
    	int* get_ptr(){
    		return ptr->p;
    	}
    };
    
    void test(){
    	int i = 0;
    	Has_Ptr hp(&i);
    	int j = 1;
    	Has_Ptr hp1(&j);
    	hp1 = hp;
    }
    int _tmain(int argc, _TCHAR* argv[])
    {
    	test();
    	return 0;
    }
    

      当一个类的成员里面有指针的时候,使用默认拷贝构造函数的时候就会造成多个对象管理同一块内存

    这样带来的后果就是,如果任意一个对象释放了这一块内存,那么其他的对象再来操作这块内存的时候就会发生预料不到的结果。

    为了避免对象中保存野指针从而引发的错误,提出了智能指针,  它能实现多个对象共享内存的自释放。

      其实这种实现有点类似于delphi中的接口,到处传来传去的,最后自释放,就是因为接口有引用计数,当引用计数为1的时候就把对象释放掉。

      C++中这种实现(C++ Primer书上借鉴来的),有几个比较巧妙的地方

    • Has_Ptr这个类其实是想保存一个int *的指针,为了避免悬垂指针的出现,我们使用了 I_Pointer这个类把悬垂指针包了一下,因此在Has_Ptr这个类的Public接口中不会出现I_Pointer,只会出现int *
    • 事实上也不能出现I_Pointer, 因为Pointer的构造函数定义成Private,不允许在外面构造,只能在friend类中构造,I_Pointer是专门为Has_Ptr实现的
    • 要记住三元组(拷贝构造,赋值操作,析构),当其中一个需要有特殊操作的时候,其他的也需要有特殊操作,这个要形成定势思维。
  • 相关阅读:
    macOS Sierra 如何打开任何来源
    centos 安装git服务器,配置使用证书登录并你用hook实现代码自动部署
    Linux下修改Mysql的用户(root)的密码
    mysql主从复制
    CentOS7下安装MySQL5.7安装与配置
    gulp安装和使用
    libiconv库的安装和使用
    Android 开发中常见的注意点
    扯一扯 C#委托和事件?策略模式?接口回调?
    Python 学习开篇
  • 原文地址:https://www.cnblogs.com/lovelyxia/p/1910796.html
Copyright © 2020-2023  润新知