[c++] 智能指针(shared_ptr, weak_ptr, unique_ptr)
(1) 共享指针是一个模板,通过模板参数指定共享指针关联的对象
(2) 共享指针中有一个计数,这个计数标志着有多少指针在共享当前这个对象。共享计数需要使用一个指针申请的空间来表示,这样方便在多个共享指针之间共享;如果直接使用一个变量,那么不便于在多个共享指针间共享。
① 构造时,引用计数初始化为 1
② 拷贝构造或者赋值的时候,引用计数增加 1
③ 析构的时候,引用计数减 1,这个时候判断引用计数是不是 0,如果是 0 的话,就将对象析构
#include <iostream>
#include <string>
#include <memory>
template <class T>
class MySharedPtr {
public:
// 默认构造函数
MySharedPtr(T *p = nullptr) {
obj_ptr_ = p;
obj_ref_count_ = new int(1);
}
// 拷贝构造函数
MySharedPtr(const MySharedPtr<T>& obj) {
obj_ptr_ = obj.obj_ptr_;
obj_ref_count_ = obj.obj_ref_count_;
(*obj_ref_count_)++;
}
// 赋值运算符
MySharedPtr<T>& operator=(const MySharedPtr<T>& obj) {
DecreaseRefCount();
++(*obj.obj_ref_count_);
obj_ptr_ = obj.obj_ptr_;
obj_ref_count_ = obj.obj_ref_count_;
return *this;
}
// 返回对象的指针
T* operator -> () {
if (obj_ptr_ == nullptr) {
throw std::runtime_error("nullptr");
}
std::cout << "operator ->\n" << std::endl;
return obj_ptr_;
}
// 返回对象
T& operator *() {
if (obj_ptr_ == nullptr) {
throw std::runtime_error("nullptr");
}
std::cout << "operator *\n";
return *obj_ptr_;
}
int UseCount() {
return *obj_ref_count_;
}
~MySharedPtr() {
DecreaseRefCount();
}
void DecreaseRefCount() {
std::cout << "before ref count: " << *obj_ref_count_ << std::endl;
(*obj_ref_count_)--;
std::cout << "after ref count: " << *obj_ref_count_ << std::endl;
if (*obj_ref_count_ == 0) {
delete obj_ref_count_;
delete obj_ptr_;
}
}
private:
T *obj_ptr_ = nullptr;
int *obj_ref_count_ = nullptr;
};
class Test {
public:
Test(int num) {
std::cout << "Test(), num = " << num << std::endl;
num_ = num;
}
~Test() {
std::cout << "~Test(), num_ = " << num_ << std::endl;
}
void Do() {
std::cout << "Do(), num = " << num_ <<std::endl;
}
private:
int num_;
};
int main() {
MySharedPtr<Test> t1(new Test(1));
// -> 运算符重载
// t1->Do() 被解释为 (t1.operator ->)->Do()
t1->Do();
std::cout << "t1 use count: " << t1.UseCount() << std::endl;
std::cout << "\n";
// 没有初始化,抛异常
MySharedPtr<Test> t2;
try {
t2->Do();
} catch (std::exception& e) {
std::cout << "exception: " << e.what() << std::endl;
}
std::cout << "\n";
MySharedPtr<Test> t3(new Test(3));
t3->Do();
std::cout << "t3 use count: " << t3.UseCount() << std::endl;
std::cout << "\n";
// 赋值运算符
t3 = t1;
t3->Do();
std::cout << "t1 use count: " << t1.UseCount() << ", t3 use count: " << t3.UseCount() << std::endl;
std::cout << "\n";
// 拷贝构造
MySharedPtr<Test> t4 = t3;
t4->Do();
std::cout << "t1 use count: " << t1.UseCount() << ", t3 use count: " << t3.UseCount() << ", t4 use count: " << t4.UseCount() << std::endl;
std::cout << "\n";
return 0;
}