这是我们C++实弹的第二次演习(模仿自定义一个智能指针),这也是我们C++的最后一篇,话不投机半句多,直接开鲁吧。跟着笔者的思路,看着每一步的描述不看代码都可以自己写出来了。
1、定义一个类
1)需要存放对象指针(类型不确定),所以是一个模板类;
2)统计对象的引用数量,需要一个计数器;
- 构造函数------每次构造一个智能指针,引用计数都从1开始
4)析构函数----当引用计数减1 等于0 的时候,需要释放智能指针内部的对象和计数器指针
template<typename T>
class CustomPtr{
private :
T* object;
int* count;
public:
//构造函数
CustomPtr() {
count = new int(1);
object = NULL;
}
//带参的构造函数
CustomPtr(T *t) : object(t) {
count = new int(1);
}
//析构函数
~CustomPtr() {
cout<<"智能指针的析构函数"<<endl;
if (--(*count) == 0) {
if (object) {
delete object;
}
delete count;
object = NULL;
count = NULL;
}
}
}
2、给智能指针添加一个拷贝构造函数
//拷贝构造函数
CustomPtr(const CustomPtr<T> &p) {
++(*p.count);
object = p.object;
count = p.count;
}
3、运算符重载(=)
特别注意:
运算符重载时,左侧的对象已经创建好了,再次赋值的时候需要先释放掉创建好的,再进行赋值,否则会出现野对象的问题;
//运算符重载
CustomPtr<T> &operator=(const CustomPtr<T> &p) {
//因为运算符重载,左侧的对象已经创建好了,所以需要释放
if (--(*count) == 0) {
if (object) {
delete object;
}
delete count;
}
++(*p.count);
object = p.object;
count = p.count;
return *this;
}
4、定义一个获取当前引用计数的方法
int use_count() {
return *(this->count);
}
截止目前为止,我们自定义的智能指针已经基本上都完成了,下面来展示一下完整的代码:
#include <iostream>
using namespace std;
template<typename T>
class CustomPtr {
private:
T *object;
int *count;
public:
CustomPtr() {
count = new int(1);
object = NULL;
}
CustomPtr(T *t) : object(t) {
count = new int(1);
}
//拷贝构造函数
CustomPtr(const CustomPtr<T> &p) {
++(*p.count);
object = p.object;
count = p.count;
}
//运算符重载
CustomPtr<T> &operator=(const CustomPtr<T> &p) {
//因为运算符重载,左侧的对象已经创建好了,所以需要释放
if (--(*count) == 0) {
if (object) {
delete object;
}
delete count;
}
++(*p.count);
object = p.object;
count = p.count;
return *this;
}
~CustomPtr() {
cout<<"智能指针的析构函数"<<endl;
if (--(*count) == 0) {
if (object) {
delete object;
}
delete count;
object = NULL;
count = NULL;
}
}
int use_count() {
return *(this->count);
}
};
5、定义“子弹”---Person类
class Person{
public:
~Person(){
cout<<"析构函数调用"<<endl;
}
};
6、实弹射击
int main(){
/**
* 手写智能指针
*/
Person* person=new Person();
Person* person1=new Person();
/**
* 智能指针的构造函数,计数+1
*/
cout<<"-----1-------"<<endl;
CustomPtr<Person> customPtr(person);
cout<<"构造函数执行后:"<<customPtr.use_count()<<endl;
/**
* 拷贝构造函数 计数+1
*/
cout<<"-----2-------"<<endl;
CustomPtr<Person> customPtr1(customPtr);
cout<<"拷贝构造函数执行后:"<< customPtr1.use_count()<<endl;
/**
* 拷贝构造函数,计数+1
*/
cout<<"-----3-------"<<endl;
CustomPtr<Person> customPtr2=customPtr;
cout<<customPtr2.use_count()<<endl;
/**
* 运算符重载 计数+1(会先创建一个对象,然后再运算符重载中释放已经创建好的默认对象,然后再赋值)
*/
cout<<"-----4-------"<<endl;
CustomPtr<Person> customPtr3;
customPtr3=customPtr;
cout<<customPtr3.use_count()<<endl;//
/**
* 运算符重载,计数+1
* 特别注意:如果在运算符重载中,不释放智能指针中的源对象person1 ,会导致person1对象成为野对象,无法释放,必须要手动释放delete
*/
cout<<"-----5-------"<<endl;
Person* person2=new Person();
CustomPtr<Person> customPtr4(person2);
CustomPtr<Person> customPtr5(person1);
customPtr5=customPtr4;
cout<<customPtr5.use_count()<<endl;
return 0;
}
//输出结果就自己去玩了
好了,截止今天,我们C++的学习就暂时告一段落了,多动手敲一下,复制了代码后,自己多修改玩玩,可以加深印象。后面我们就进入JNI开发了。
网友评论