本节将实现一个名为SmartPointer的简化版本的shared_ptr模板类,相关C++代码如下。
本文引用自作者编写的下述图书; 本文允许以个人学习、教学等目的引用、讲授或转载,但需要注明原作者"海洋饼干叔
叔";本文不允许以纸质及电子出版为目的进行抄摘或改编。
1.《Python编程基础及应用》,陈波,刘慧君,高等教育出版社。免费授课视频 Python编程基础及应用
2.《Python编程基础及应用实验教程》, 陈波,熊心志,张全和,刘慧君,赵恒军,高等教育出版社Python编程基础及应用实验教程
3. 《简明C及C++语言教程》,陈波,待出版书稿。免费授课视频
//Project - SmartPointer
#include
using namespace std;
class Fish {
public:
string sName;
Fish(const string& name){
sName = name;
cout << "Fish Constructor called: " << sName << endl;
}
void sayHello(){
cout << "Aloha: " << sName << endl;
}
~Fish(){
cout << "Fish Destructor called: " << sName << endl;
}
};
template <typename T>
class SmartPointer {
private:
T* ptr; //原始指针
int* refCount; //指向引用计数的指针
void releaseReference(){ //释放对对象的引用
if (!ptr)
return;
(*refCount)--;
if (*refCount==0){
delete ptr; ptr = nullptr;
delete refCount; refCount = nullptr;
}
}
public:
SmartPointer(T* p=nullptr){
ptr = p;
refCount = new int;
*refCount = 1;
}
~SmartPointer(){
releaseReference();
}
//拷贝构造函数
SmartPointer(const SmartPointer& r) {
cout << "Copy constructor of SmartPointer." << endl;
ptr = r.ptr;
refCount = r.refCount;
(*refCount)++;
}
//重载=操作符
SmartPointer& operator=(const SmartPointer& r){
cout << "operator=(const SmartPointer&)." << endl;
if (&r == this)
return *this;
releaseReference();
ptr = r.ptr;
refCount = r.refCount;
(*refCount)++;
return *this;
}
//重载*操作符
T& operator*(){
cout << "operator*() of SmartPointer." << endl;
if (ptr)
return *ptr;
throw exception();
}
//重载->操作符
T* operator->(){
cout << "operator->() of SmartPointer." << endl;
if (ptr)
return ptr;
throw exception();
}
//查询引用计数
int referenceCount(){
return *refCount;
}
};
int main() {
SmartPointer<Fish> f1(new Fish("Dora"));
SmartPointer<Fish> f2(new Fish("Tom"));
auto f3 = f1; //调用f3的拷贝构造函数,以f1为实参
f2 = f1; //调用f2的operator=()函数,以f1为实参,间接导致Tom鱼被释放
(*f2).sayHello(); //调用f2的operator*()函数
f2->sayHello(); //调用f2的operator->()函数
cout << "Refernce count of Dora fish: " << f2.referenceCount() << endl;
return 0;
}
上述代码的执行结果为:
Fish Constructor called: Dora
Fish Constructor called: Tom
Copy constructor of SmartPointer.
operator=(const SmartPointer&).
Fish Destructor called: Tom
operator*() of SmartPointer.
Aloha: Dora
operator->() of SmartPointer.
Aloha: Dora
Refernce count of Dora fish: 3
Fish Destructor called: Dora
类似于第7章中介绍的模板函数,SmartPointer被设计为一个模板类,其类型参数T需要在使用该类时于<>内提供。
🚩第22 ~ 26行:SmartPointer对象包含两个私有属性,其中,ptr为指向动态对象的原始指针;refCount则为指向引用计数的指针。如前所述,该引用计数用于记录指向动态对象的存活智能指针对象的个数。
🚩第27 ~ 35行:下述情况之一,releaseReference()成员函数将被调用,以释放该指针对动态对象的引用。
🚩第28 ~ 29行:如果智能指针是空指针,直接返回。
🚩第30行:引用计数递减。
🚩第31 ~ 34行:如果引用计数归零,说明该指针所指向的动态对象已经不被需要,将其释放,同时释放引用计数。
🚩第38 ~ 42行:构造函数接受一个动态对象的指针作为参数。函数体内,原始指针得到保存,引用计数被创建并置1。
🚩第44 ~ 46行:析构函数内调用releaseReference()函数释放指针对动态对象的引用。如果该智能指针是指向该动态对象的最后一个存活的智能指针,该函数会释放动态对象。
🚩第49 ~ 54行:拷贝构造函数。该函数通过复制来初始化一个新的智能指针对象。函数体完成了下述工作:
🚩第57 ~ 65行:operator=()操作符函数用于对一个已经存在的智能指针对象进行赋值。
🚩第59 ~ 60行:如果智能指针对象自己赋值给自己,什么也不做,直接返回*this做为表达式的值。请读者注意,a = a这种表达式在语法上是合法的,虽然多数编译器会给出警告信息。
🚩第61行:在绑定到新的动态对象之前,先释放对原动态对象的引用。
🚩第62 ~ 64行:绑定至新的动态对象,递增引用计数。
🚩第65行:返回*this作为表达式的值。
🚩第69 ~ 74行:间接操作符*的重载函数。当对一个智能指针使用间接操作符时,该函数会被调用,以获得其所指向的动态对象的引用。
🚩第71 ~ 72行:如果原始指针不为空,返回所指向的动态对象的引用。
🚩第73行:对一个空指针使用间接操作符是非法的,抛出异常(exception)▲。
🚩第77 ~ 82行:指向操作符->的重载函数。当对一个智能指针使用指向操作符时,该函数会被调用。该函数预期返回原始指针。
🚩第79 ~ 80行:如果原始指针非空,返回原始指针。
🚩第81行:对一个空指针应用指向操作符是非法的,抛出异常。
🚩第85 ~ 87行:查询智能指针所指向的动态对象的引用计数,该引用计数表明当前指向该动态对象的智能指针的数量。
接下来,main()函数演示了上述SmartPointer类型的使用方法。
🚩第91 ~ 92行:创建Dora鱼、Tom鱼及相关智能指针。执行结果的第1 ~ 2行对应两条鱼的构造输出。
🚩第93行:f3的拷贝构造函数被执行,以f1为实参。执行结果的第3行对应拷贝构造函数的输出。
🚩第94行:该行代码执行前f2已存在,故f2的operator=()函数被执行,以f1为实参。执行结果的第4行对应operator=()函数的输出。当前,f2是指向Tom鱼的唯一智能指针,f2的被赋值将间接导致Tom鱼被释放,执行结果的第5行对应Tom鱼的析构输出。
🚩第95行:对智能指针f2应用间接操作符以获取f2所指向的动态对象的引用,本行事实上导致了f2的operator*()函数的执行,该函数出的输出见执行结果的第6行。以返回的Dora鱼对象的引用为基础,sayHello()成员函数被执行,执行结果的第7行可以看到来自Dora鱼的问候。
🚩第96行:对智能指针f2应用指向操作符,本行事实上导致了f2的operator->()函数的执行,其输出对应执行结果的第8行。以该函数返回的Dora鱼的原始指针为基础,sayHello()成员函数被执行,执行结果的第9行可再次看到来自Dora鱼的问候。
🚩第97行:目前为止,共有f1、f2和f3共三个智能指针指向Dora鱼,referenceCount()返回Dora鱼的引用计数,其值应为3,见执行结果的第10行。
到了main()函数的结尾,智能指针f1、f2和f3作为栈对象,相继被析构并释放对Dora鱼的引用。其中,最后一个被析构的智能指针发现Dora鱼的引用计数归零,将其释放。执行结果的第11行,对应Dora鱼的析构输出。
为了帮助更多的年轻朋友们学好编程,作者在B站上开了两门免费的网课,一门零基础讲Python,一门零基础C和C++一起学,拿走不谢!
如果你觉得纸质书看起来更顺手,目前Python有两本,C和C++在出版过程中。