当前位置:网站首页>智能指针实现猜想
智能指针实现猜想
2022-07-30 12:13:00 【君梦如烟Brian】
通过强引用和弱引用实现的自动内存管理预想,仅实现了管理内存的部分,仍有许多C++11的功能未能实现。
SharedPtr => std::shared_ptr
SentinelPtr => std::weak_ptr (为什么这样取,因为SentinelPtr 行为上更像是SharedPtr 的观察窗口)
首先,实现了SharedPtr, 这个很好理解。只要出现拷贝行为就将引用计数+1,由于多个对象间共享计数器,因此计数器必须也是指针。
难点在于,引入SentinelPtr后,同时保持SharedPtr 的行为时的条件控制。
比较形象的话,我们可以将强引用看作值的计数器,那么弱指针就相当于强引用的计数器。
欠缺:
(-) 功能还没完全实现,只是将涉及计数的部分实现了。
(-) 计数器非线程安全
template<typename T>
class SentinelPtr;
template <typename T>
class SharedPtr {
size_t* ref_counter_ = nullptr;// 强引用计数器
T* val_ = nullptr; // 值引用
size_t * soft_ref_counter_ = nullptr; // 弱引用计数器
// template <T>
friend class SentinelPtr<T>;
public:
SharedPtr operator=(const SharedPtr& rhs) = delete;
SharedPtr():ref_counter_(nullptr), val_(nullptr), soft_ref_counter_(nullptr){
}
SharedPtr(T val) :val_(new T(val)), ref_counter_(new size_t(1)), soft_ref_counter_(new size_t(1)) {
}
SharedPtr(T* val_pointer) {
if (val_pointer != nullptr) {
val_ = val_pointer;
ref_counter_ = new size_t(1);
soft_ref_counter_ = new size_t(1);
}
else {
val_ = nullptr;
ref_counter_ = nullptr;
soft_ref_counter_ = nullptr;
}
}
SharedPtr(const SharedPtr<T>& rhs) {
// 歧义: 引用计数本身必须自增,const的表达有点奇怪
if(val_ != rhs.val_) try_release();
soft_ref_counter_ = rhs.soft_ref_counter_;
ref_counter_ = rhs.ref_counter_;
val_ = rhs.val_;
// rhs通过默认构造的
if (val_ == nullptr) return;
assert(soft_ref_counter_ != nullptr);
assert(ref_counter_ != nullptr);
(*soft_ref_counter_)++;
(*ref_counter_)++;
}
~SharedPtr() {
if (val_ == nullptr) return;
assert(ref_counter_ != nullptr);
assert(val_ != nullptr);
try_release();
soft_ref_counter_ = nullptr;
ref_counter_ = nullptr;
val_ = nullptr;
}
public:
size_t use_count()const {
if (ref_counter_) return *ref_counter_;
return 0;
}
private:
// 释放了val就return true
void try_release() {
// 可能通过空指针构造的对象
if (!soft_ref_counter_) return;
// 弱引用计数, 后面再一起结算
(*soft_ref_counter_)--;
assert(ref_counter_ != nullptr);
(*ref_counter_)--;
// 强引用计数为0, 释放值
if (*ref_counter_ == 0) {
delete val_;
val_ = nullptr;
}
// 弱引用计数为0, 释放所有计数器
if ((*soft_ref_counter_) == 0) {
delete ref_counter_;
delete soft_ref_counter_;
ref_counter_ = nullptr;
soft_ref_counter_ = nullptr;
}
}
};
template<typename T>
class SentinelPtr {
size_t* ref_counter_; // 强引用计数器
size_t* soft_ref_counter_; // 弱引用计数器(相当于强引用器的引用计数)
T* val_; // 提升值
public:
SharedPtr<T> update() {
if (!soft_ref_counter_ || !ref_counter_) return SharedPtr<T>;
SharedPtr<T> ex;
ex.ref_counter_ = ref_counter_;
ex.soft_ref_counter_ = soft_ref_counter_;
ex.val_ = val_;
(*soft_ref_counter_)++;
(*ref_counter_)++;
return ex;
}
SentinelPtr(SharedPtr<T> sha_ptr) {
ref_counter_ = sha_ptr.ref_counter_;
soft_ref_counter_ = sha_ptr.soft_ref_counter_;
val_ = sha_ptr.val_;
if (soft_ref_counter_) {
assert(ref_counter_ != nullptr);
(*soft_ref_counter_)++;
}
else {
assert(ref_counter_ == nullptr);
assert(soft_ref_counter_ == nullptr);
assert(val_ == nullptr);
}
}
SentinelPtr(const SentinelPtr<T>& st_ptr) {
if(soft_ref_counter_ != st_ptr)
try_release();
ref_counter_ = st_ptr.ref_counter_;
soft_ref_counter_ = st_ptr.soft_ref_counter_;
val_ = st_ptr.val_;
if (soft_ref_counter_) {
assert(ref_counter_ != nullptr);
(*soft_ref_counter_)++;
}
else {
assert(ref_counter_ == nullptr);
assert(soft_ref_counter_ == nullptr);
assert(val_ == nullptr);
}
}
~SentinelPtr() {
try_release();
ref_counter_ = nullptr;
val_ = nullptr;
soft_ref_counter_ = nullptr;
}
/* size_t use_count() { if (!soft_ref_counter_ || !ref_counter_) return 0; return (*ref_counter_); } */
private:
void try_release() {
if (!soft_ref_counter_) return;
assert(ref_counter_ != nullptr);
(*soft_ref_counter_)--;
if (*soft_ref_counter_ == 0) {
delete soft_ref_counter_;
delete ref_counter_;
soft_ref_counter_ = nullptr;
ref_counter_ = nullptr;
}
}
};
int main()
{
// default ctor
{
SharedPtr<int> emp_ptr;
}
// ctor(val)
{
SharedPtr<int> ptr(4);
assert(ptr.use_count() == 1);
}
// ctor(valpointer)
{
SharedPtr<int> b(new int(4));
assert(b.use_count() == 1);
}
// dctr
{
SharedPtr<int> outer(4);
{
SharedPtr<int> inner(outer);
assert(outer.use_count() == inner.use_count());
assert(inner.use_count() == 2);
}
assert(outer.use_count() == 1);
}
{
SharedPtr<int> outer(4);
SentinelPtr<int> p = outer;
assert(outer.use_count() == 1);
}
return 0;
}
边栏推荐
- 为什么说Prometheus是足以取代Zabbix的监控神器?
- 力扣——15. 三数之和
- Apifox generates interface documentation tutorial and operation steps
- Rust 从入门到精通02-安装
- Flexible distribution parameters of mechanical system modeling and control of research and development
- MySQL【多表查询】
- JS事件参数对象event
- Verilog grammar basics HDL Bits training 08
- 力扣——11.盛最多水的容器
- Matlab基础(4)——矩阵
猜你喜欢

反转链表-迭代反转法

历时两月,终拿字节跳动offer,算法面试题分享「带答案」

11 年膨胀 575 倍,微信为何从“小而美”变成了“大而肥”?

【Kaggle:UW-Madison GI Tract Image Segmentation】肠胃分割比赛:赛后复盘+数据再理解

物理服务器与虚拟机:主要区别和相似之处

OneNote如何修改已有的笔记本为默认的快速笔记?

Breaking the principle and introducing SQL, what does MongoDB want to do???

win下怎么搭建php环境的方法教程

Program environment and preprocessing (detailed)

【32. 图中的层次(图的广度优先遍历)】
随机推荐
Concepts of cloud-native applications and 15 characteristics of cloud-native applications
北上广线下活动丨年底最不可错过的技术聚会都齐了
int a=8,a=a++,a? int b=8,b=b+1,b?
【语音识别】基于GMM-HMM的语音识别系统
MySQL中的select,from, join, on where groupby等执行顺序
MySQL【多表查询】
Matlab基础(1)——基础知识
[SCTF2019]Flag Shop
结合实战,浅析GB/T28181(三)——实况点播
LeetCode_236_Last Common Ancestor of a Binary Tree
CMake库搜索函数居然不搜索LD_LIBRARY_PATH
亚洲高校首现KDD博士论文奖:清华裘捷中获Runner Up奖,WINNER奖也是位华人
小心 transmittable-thread-local 的这个坑
Farmers on the assembly line: I grow vegetables in a factory
备战金九银十!2022面试必刷大厂架构面试真题汇总+阿里七面面经+架构师简历模板分享
Scheduling of combined electric-heating system based on multi-objective two-stage stochastic programming method
ECCV 2022 | 新加坡国立大学提出:全新可恢复型模型遗忘框架LIRF!
Rust from entry to proficient 02-installation
C#调用explorer.exe打开指定目录
Zhou Hongyi: Microsoft copied the 360 security model and became the largest security company in the United States