C++自己封装的简易的较安全的智能指针

1.首先,基本的智能指针的功能参考自:

C++面试题(四)——智能指针的原理和实现_普通网友的博客-CSDN博客_智能指针的实现

自己实现智能指针_leechow007的博客-CSDN博客_自己实现智能指针

C++手把手带你实现一个智能指针 - 知乎

c++智能指针中的reset成员函数_lzn211的博客-CSDN博客_c++ reset

智能指针shared_ptr reset()_fxlego的博客-CSDN博客_智能指针reset

2.实现智能指针能指向数组的功能参考自:

C++重写SharedArrayPtr——指向数组的智能指针类_lzq8090的博客-CSDN博客

3.保证智能指针指向的空间是分配在堆区的,参考自:

c++中能否判断一个指针指向栈还是堆? - 知乎

C++-如何判断指针指向的是堆内存还是栈内存 - 话题 - 文江博客

C++的查看指针指向空间的所在的区域(是堆还是栈或者静态)和大小_H-KING的博客-CSDN博客

注:不同平台的数据存储方式可能不一样,需要自行判断是大端存储还是小端存储。本文代码采用的是用变量地址离堆区地址近还是栈区地址近来判断的判断。

4.抛出异常及一些运算符的重载参考自:

C++Primer学习笔记(4)_qq_42987967的博客-CSDN博客

C++语言之重载运算符()/[]/++/->等运算符_姚镜堂的博客-CSDN博客_重载()运算符

5.总结

需要实现:

基本构造函数、拷贝构造函数、拷贝运算符、析构函数、

重载解引用运算符*、指针运算符->、数组索引运算符[]、比较运算符bool、

STL中智能指针还自带的函数use_count、get、reset

6.最终代码:

#pragma once
//my_ptr.h
template<typename T>
class my_ptr {
public:
    //智能指针的基本的几个函数
    explicit my_ptr(T* p) :ptr(p), count(new int), isArray(0), arrayLength(1) {//基本非数组构造函数
        if (!p) {//不允许传入空指针
            throw p;
        }
        T* test_heap = new T;//检测是否分配在了堆区
        T test_stack;
        //cout << ptr << "  " << test_stack << endl;
        long long a = abs(long long(p) - long long(test_heap));
        long long b = abs(long long(p) - long long(&test_stack));
        if (a > b) {
            throw exception("未分配在堆区");
        }
        delete test_heap;
        *count = 1;
    }
    explicit my_ptr(T* p, int len) :ptr(p), count(new int), isArray(1), arrayLength(len) {//基本数组构造函数
        if (!p) {//不允许传入空指针
            throw p;
        }
        T* test_heap=new T;//检测是否分配在了堆区
        T test_stack;
        //cout << ptr << "  " << &test_stack << endl;
        long long a =abs( long long(p) - long long(test_heap) );
        long long b = abs(long long(p) - long long(&test_stack));
        if ( a > b ) {
            throw exception("未分配在堆区");
        }
        delete test_heap;
        *count = 1;
    }
    my_ptr(const my_ptr& src) :isArray(1) {//拷贝构造函数
        ptr = src.ptr;
        count = src.count;
        arrayLength = src.arrayLength;
        isArray = src.isArray;
        ++(*count);
    }
    my_ptr(const my_ptr&& src) = delete;//删除移动构造

    my_ptr& operator=(const my_ptr& src) {//拷贝赋值函数
        --(*count);
        if ((*count) == 0)delete ptr;
        ptr = src;
        count = src.ptr;
        arrayLength = src.arrayLength;
        isArray = src.isArray;
        ++(*count);
        return *this;
    }

    my_ptr& operator=(const my_ptr&& src) = delete;//删除移动拷贝

    ~my_ptr() {
        if (*count == 1) {
            //如果当前只有该智能指针指向ptr所指空间,那么该智能指针销毁时,ptr所指向的空间也应销毁
            delete count;
            // if (isArray)delete[] ptr;//指针若指向数组需调用delete[]
           //  else delete ptr;
        }
        else {
            //否则将count所指计数值自减1即可
            --(*count);
        }
    }

    //使智能指针更像指针的功能部分
    T& operator*() {//重载解引用运算符,使智能指针更像指针
        if (!ptr) {
            throw ptr;
        }
        return *ptr;
    }
    T* operator->() {//重载解指针运算符,使智能指针更像指针
        if (!ptr) {
            throw ptr;
        }
        return ptr;
    }
    T operator[](int i){//用于数组索引
        if (!ptr) {
            throw ptr;
        }
        if (i >= arrayLength) {
            throw runtime_error("数组越界");
        }
        return ptr[i];
    }
        operator bool() {//使用智能指针进行判断时使其表现为ptr的判断
        return ptr;
    }


     //使智能指针更像官方的智能指针的部分
    T* get() {
        return ptr;//返回智能指针所引用的指针
    }

    int use_count() {//返回引用个数
        return *count;
    }
    void reset() {
        if (--(*count) == 0) {
            delete ptr;
        }
        ptr = nullptr;
        count = nullptr;
        isArray = 0;
        arrayLength = 0;
    }

protected:
    //控制智能指针禁止分配在堆区
    void* operator new(size_t t) {}
    void operator delete(void* p) {}

private:
    //智能指针中所引用的指针所指向的空间和计数指针所指向的空间是共享的
    T* ptr;//引用空间指针
    int* count;//计数指针,其意义为指向ptr空间的智能指针的个数
    bool isArray;//判断指针是否指向数组
    int arrayLength;//判断指针的指向数组长度
};
//测试
#include <iostream>
#include "my_ptr.h"
using namespace std;


int main()
{

  //  return 0;
    //分配数组
    int* p = new int[4]{ 0,1,2,3 };
    my_ptr<int> mp(p, 4);
    cout << mp.use_count() << endl;
    cout << mp[2] << endl;
    /*
    int b = 0;
    my_ptr<int> mp1(&b);//智能指针所指区域为栈,报错
    */
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值