C++ 智能指针 实现 测试

本文详细介绍了C++中智能指针(SmartPointer)的工作原理,包括引用计数机制,以及如何通过模板类实现。重点讲解了内存管理中的注意事项和常见陷阱,如正确取指针、操作符优先级等,通过实例演示了智能指针在避免内存泄露和程序崩溃上的作用。
摘要由CSDN通过智能技术生成

        在java这样的高级语言中,我们一般不用手动管理内存,但在C++中,堆中的内存需要手动回收,当同一块内存被释放多次时,可能引起程序的崩溃和异常,这就引出来了一个内存管理的问题,一种解决方案是使用智能指针(SmartPointer),它内部包含了两个值:一个模板指针,一个计数器。该智能指针通过引用计数的方式来决定什么时候来释放内存:

       1. 当初始化构造时,对传入的指针参数记count为0或1(如果传入一个nullptr类型,那就把count设为0,否则为1)

        2.发生一次拷贝构造时,让当前this的两个内部指针指向传入的参数的对应指针,然后让count值加一。

        3.重载等于号:首先让当前this的count减一,如果计数为0,那么就开始销毁当前计数器和指针,然后,让当前this的两个内部指针指向传入参数的对应指针,然后让新的count加一,代表当前存储对象的引用次数多了一次。

        4.获得引用次数,直接返回当前对象的count值

        5.重载*号,对智能指针取*,代表获取该智能指针内部存储的对象的值。

        6.重载->号,对智能指针取->,代表获取该智能指针内部存储对象的地址(可以这样理解)

这些说完以后,说一些踩坑点:

        1.注意什么时候取指针,什么时候不取指针(qaq感觉像废话)

        2.注意各操作符的优先级(我在这里踩大坑了)

让我们看c++下使用模板类进行实现的具体代码:(借鉴过一些设计

#include <bits/stdc++.h>
using namespace std;


template<typename T>
class SmartPointer{
private:
	T* pointer;
	int* count;
public:
	SmartPointer(T *ptr= nullptr):pointer(ptr){
		if (ptr)count=new int(1);
		else count=new int(0);
	}
	SmartPointer(const SmartPointer& smartPointer){
		this->pointer=smartPointer.pointer;
		this->count=smartPointer.count;
		(*count)++;//取count指向的位置上存储的值 然后加一
	}
	/*override the = operator  when this happening, the ptr of this will minus 1 .if it become zero ,we have to free
	 the memory */
	SmartPointer& operator=(const SmartPointer& smartPointer){
		if(this->pointer==smartPointer.pointer){return *this;}
		(*count)--;
		if ((*count)==0){delete pointer;delete count;}
		this->pointer=smartPointer.pointer;
		this->count=smartPointer.count;
		(*count)++;
		return *this;//this是当前对象的地址,*this代表当前对象的值
	}
	int useCount(){
		return *count;
	}
	T& operator*(){//可以不做判断 取的是值 所以我们要取pointer上存储的值
		//if (pointer== nullptr)cout<<"this is a null pointer!\n";
		return  *pointer;//or you can return *(this->pointer);
	}
	T* operator->(){//取的是指针 所以我们直接返回pointer
		//if (pointer== nullptr)cout<<"this is a null pointer!\n";
		return pointer;
	}
	~SmartPointer(){
		(*count)--;
		if (*count==0){delete pointer;delete count;}
	}
};

        那么我们开始测试,我选用了int* 以及自建的Node结构体来测试:


struct Node{
	int val;
	Node* next;
	Node(int v):val(v),next(nullptr){}
};
Node* createList(vector<int>nums){
	Node *dummy=new Node(-1),*head=dummy;
	for (int i = 0; i < nums.size(); ++i) {
		head->next=new Node(nums[i]);
		head=head->next;
	}
	Node* d=dummy->next,*e=dummy;
	free(dummy);//这里是为了方便友友们验证我说的重复释放一块内存导致的程序崩溃
//	free(e); //if you free the same place twice,the program will collapse.
	return d;
}
void reversePrint(Node* cur){//逆序递归打印链表 纯属抖机灵
	if (cur== nullptr)return;
	reversePrint(cur->next);
	cout<<cur->val<<" ";
}

        现在我们来看测试结果:

int main() {
	int* p=new int(11);
	SmartPointer<int>ptr1(p);
	cout<<"the useCount of ptr1 is: "<<ptr1.useCount()<<'\n';
	SmartPointer<int>ptr2(ptr1);
	cout<<"the useCount of ptr2 is: "<<ptr2.useCount()<<'\n';
	SmartPointer<int>ptr3=ptr2;
	cout<<"the useCount of ptr3 is: "<<ptr3.useCount()<<'\n';
	ptr3.~SmartPointer();
	cout<<"after the ptr3 is deleted, the useCount of ptr2 is: "<<ptr2.useCount()<<'\n';
	int a=*ptr1;
	cout<<"a is: "<<a<<'\n';
	int *b=(ptr1.operator->());
	cout<<"*b is:"<<*b<<'\n';
	//the test of the Node
	Node* nodePtr=new Node(12);
	SmartPointer<Node>ptr4(nodePtr);
	cout<<"the useCount of ptr4 is: "<<ptr4.useCount()<<'\n';
	SmartPointer<Node> ptr5=ptr4;
	cout<<"the useCount of ptr5 is: "<<ptr5.useCount()<<'\n';
	Node node=*ptr5;
	cout<<"the value of node is: "<<node.val<<'\n';
	Node* node1=ptr5.operator->();
	cout<<"the value of node1 is: "<<node1->val<<'\n';
	ptr5.~SmartPointer();
	ptr4.~SmartPointer();
	cout<<node1->val<<" ,this is a random value cause it is deleted by our smartPointer\n";
	SmartPointer<Node>myList= createList({1,2,3,4,5});
	cout<<"if the list is created normally,you will see this line,otherwise,the program is collapsed\n";
	SmartPointer<Node>myList2(myList);
	cout<<"the useCount of the head of the list is: "<<myList.useCount()<<'\n';
	myList.~SmartPointer();
	cout<<"the useCount of the head of the list is: "<<myList2.useCount()<<'\n';
	cout<<"try to print the list in reverse order: \n";
	reversePrint(myList2.operator->());
	SmartPointer<Node>ptr7(nullptr);
	cout<<"\nthe useCount of the ptr7 is :"<<ptr7.useCount()<<'\n';
	return 0;
}

        这三块代码直接复制粘贴到main.cpp里就能运行,各位可以自己运行一下。

运行结果如下:

the useCount of ptr1 is: 1
the useCount of ptr2 is: 2
the useCount of ptr3 is: 3
after the ptr3 is deleted, the useCount of ptr2 is: 2
a is: 11
*b is:11
the useCount of ptr4 is: 1
the useCount of ptr5 is: 2
the value of node is: 12
the value of node1 is: 12
8985904 ,this is a random value cause it is deleted by our smartPointer
if the list is created normally,you will see this line,otherwise,the program is collapsed
the useCount of the head of the list is: 2
the useCount of the head of the list is: 1
try to print the list in reverse order:
5 4 3 2 1
the useCount of the ptr7 is :0

Process finished with exit code 0

       可以看到我们的程序的运行结果符合预期。

如果有疑惑的地方,欢迎留言

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值