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博客
等运算符_姚镜堂的博客-CSDN博客_重载()运算符">C++语言之重载运算符()/[]/++/->等运算符_姚镜堂的博客-CSDN博客_重载()运算符
5.总结需要实现:
基本构造函数、拷贝构造函数、拷贝运算符、析构函数、
重载解引用运算符*、指针运算符->、数组索引运算符[]、比较运算符bool、
STL中智能指针还自带的函数use_count、get、reset
6.最终代码:#pragma once //my_ptr.h templateclass 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#include "my_ptr.h" using namespace std; int main() { // return 0; //分配数组 int* p = new int[4]{ 0,1,2,3 }; my_ptr mp(p, 4); cout << mp.use_count() << endl; cout << mp[2] << endl; }