C++ BitArray 引用计数实现
#ifndef __BITARRAY__ //数组不支持多线程同时访问,没有对引用计数以及分配的资源做任何锁处理
#define __BITARRAY__ 1 //越界访问修改为抛出异常 #ifdef __BIT_DEBUG__ //__BIT_DEBUG__是调试用的宏定义
#include <cstdio>
#endif #ifdef __cplusplus > 201103L
#include <cstdint>
#else
#include <stdint.h>
#define nullptr NULL
#define noexcept throw()
#endif #define __BIT_ERRMSG_LEN__ 512 #include <cstring>
#include <stdexcept> class BitArray
{
private:
enum __e_bit_size {bit = }; class __Ref_Array //引用计数类
{
public:
__Ref_Array(int64_t __size)
:m_ref_count(), m_size(__size)
{
#ifdef __BIT_DEBUG__
fprintf(stderr, "__Ref_Array ctor @addr: %p with size:%ld\n", this, __size);
#endif
init();
} ~__Ref_Array()
{
#ifdef __BIT_DEBUG__
fprintf(stderr, "__Ref_Array dtor @addr: %p with size:%ld\n", this, __size);
#endif
delete[] m_array;
} __Ref_Array(const __Ref_Array& o)
:m_ref_count(),
m_size(o.m_size),
m_array_size(o.m_array_size),
m_used(o.m_used)
{
#ifdef __BIT_DEBUG__
fprintf(stderr, "__Ref_Array copytor @addr: %p with @addr: %p && size:%ld\n", this, &o, __size);
#endif
m_array = new int8_t[m_array_size];
memcpy(m_array, o.m_array, m_array_size);
} inline bool
get(int64_t __pos) const
{return *(m_array + slot_bit(__pos)) & mask(__pos);} inline void
set(int64_t __pos)
{
*(m_array + slot_bit(__pos)) |= mask(__pos);
m_used ++;
} inline void
clear(int64_t __pos)
{
*(m_array + slot_bit(__pos)) &= ~mask(__pos);
m_used --;
} inline void
reset()
{
std::memset(m_array, , m_array_size);
m_used = ;
} inline int64_t
length() const
{return m_size;} inline int64_t
size() const
{return m_size;} inline int64_t
used() const
{return m_used;} inline int64_t
refCount() const
{return m_ref_count;} inline bool
sizeRange(int64_t __pos) const
{return __pos >= && __pos < m_size;} inline int64_t
sharedPlus()
{return ++ m_ref_count;} inline int64_t
sharedSub()
{return -- m_ref_count;} inline bool
isShared() const
{return m_ref_count > ;} private:
inline void
init()
{
m_array_size = nslot(m_size);
m_array = new int8_t[m_array_size];
reset();
} inline int64_t
slot_bit(int64_t __n) const
{return __n / bit;} inline int64_t
nslot(int64_t __size) const
{return slot_bit(__size + bit - );} inline int8_t
mask(int64_t __pos) const
{return int8_t() << (__pos % bit);} private:
int8_t m_array; //位数组存储
int64_t m_ref_count; //引用计数
int64_t m_size; //引用计数大小
int64_t m_array_size; //分配的int8_t数组大小
int64_t m_used; //已经使用的bit位数
}; private:
class BitProxy //代理类 为了区分 x = ba[?]; 和 ba[?];
{
BitProxy(BitArray& ba, int64_t pos)
:m_array(ba), m_pos(pos)
{} BitProxy& operator = (const BitProxy& rh)
{
if(rh)
m_array.set(m_pos);
else{
m_array.clear(m_pos);
} return *this;
} BitProxy& operator = (bool status)
{
if(status)
m_array.set(m_pos);
else{
m_array.clear(m_pos);
} return *this;
} operator bool() const
{
return m_array.get(m_pos);
} private:
BitArray& m_array;
int64_t m_pos;
}; public: BitArray() noexcept //无参数构造函数
:m_ref(nullptr)
{
#ifdef __BIT_DEBUG__
fprintf(stderr, "BitArray ctor @addr: %p with nullptr ...\n", this);
#endif
} BitArray(int64_t size) noexcept //构造函数
:m_ref(size > new __Ref_Array(size) : nullptr)
{
#ifdef __BIT_DEBUG__
fprintf(stderr, "BitArray ctor @addr: %p with size: %d ...\n", this, size);
#endif
} ~BitArray() //析构函数
{release()} BitArray(const BitArray& o) noexcept //copy构造函数
m_ref(o.m_ref)
{
#ifdef __BIT_DEBUG__
fprintf(stderr, "BitArray copy tor @addr: %p with other BitArray @addr: %p ...\n", this, &o);
#endif
} #ifdef __cplusplus >= 201103L
BitArray(BitArray&& o) noexcept //move构造函数
m_ref(o.m_ref)
{
#ifdef __BIT_DEBUG__
fprintf(stderr, "BitArray move tor @addr: %p <--- other BitArray @addr: %p ...\n", this, &o);
#endif
o.m_ref = nullptr;
}
#endif BitArray& operator=(const BitArray& o) //赋值运算符
{
if(m_ref != o.m_ref)
{
release();
m_ref = o.m_ref;
#ifdef __BIT_DEBUG__
fprintf(stderr, "BitArray assign @addr: %p with other BitArray @addr: %p ...\n", this, &o);
#endif
if(m_ref)
m_ref->sharedPlus();
}
} const BitProxy
operator[] (int64_t pos) const //下标运算符
{return BitProxy(const_cast<BitArray&>(*this), pos);} BitProxy
operator[] (int64_t pos) //下标运算符
{return BitProxy(*this, pos);} public:
inline bool
get(int64_t pos) const throw(std::out_of_range)
{
if(!m_ref || !m_ref->sizeRange(pos))
{
char errmsg[__BIT_ERRMSG_LEN__] = {}; snprintf(errmsg, sizeof(errmsg), "out of range in get -> pos : %d | size : %d\n", pos, size()); throw std::out_of_range(errmsg);
}
else
return m_ref->get(pos);
} inline bool
set(int64_t pos) const throw(std::out_of_range)
{
if(!m_ref || !m_ref->sizeRange(pos))
{
char errmsg[__BIT_ERRMSG_LEN__] = {}; snprintf(errmsg, sizeof(errmsg), "out of range in set -> pos : %d | size : %d\n", pos, size()); throw std::out_of_range(errmsg);
}
else if(m_ref->get(pos))
{
return true;
}
else
{
if(m_ref->isShared())
{
__Ref_Array* last_ref = m_ref; m_ref = new __Ref_Array(*last_ref); last_ref->sharedSub();
} return m_ref->get(pos);
}
} inline bool
clear(int64_t pos) const throw(std::out_of_range)
{
if(!m_ref || !m_ref->sizeRange(pos))
{
char errmsg[__BIT_ERRMSG_LEN__] = {}; snprintf(errmsg, sizeof(errmsg), "out of range in clear -> pos : %d | size : %d\n", pos, size()); throw std::out_of_range(errmsg);
}
else if(!m_ref->get(pos))
{
return true;
}
else
{
if(m_ref->isShared())
{
__Ref_Array* last_ref = m_ref; m_ref = new __Ref_Array(*last_ref); last_ref->sharedSub();
} return m_ref->clear(pos);
}
} inline void
reset()
{if(m_ref) m_ref->reset();} inline int64_t
size()
{return m_ref ? m_ref->size() : ;} inline int64_t
length()
{return m_ref ? m_ref->length() : ;} inline int64_t
count()
{return m_ref ? m_ref->count() : ;}
private:
inline void
release() //引用计数释放
{
#ifdef __BIT_DEBUG__
fprintf(stderr, "BitArray released @addr: %p current reference : %d ...\n", this, m_ref->refCount());
#endif
if(m_ref && (m_ref->sharedSub() == ))
{
delete m_ref;
m_ref = null;
}
} __Ref_Array* m_ref;
}; #endif
C++ BitArray 引用计数实现的更多相关文章
- Objective-C内存管理之引用计数
初学者在学习Objective-c的时候,很容易在内存管理这一部分陷入混乱状态,很大一部分原因是没有弄清楚引用计数的原理,搞不明白对象的引用数量,这样就当然无法彻底释放对象的内存了,苹果官方文档在内存 ...
- swift学习笔记5——其它部分(自动引用计数、错误处理、泛型...)
之前学习swift时的个人笔记,根据github:the-swift-programming-language-in-chinese学习.总结,将重要的内容提取,加以理解后整理为学习笔记,方便以后查询 ...
- C++ 引用计数技术及智能指针的简单实现
一直以来都对智能指针一知半解,看C++Primer中也讲的不够清晰明白(大概是我功力不够吧).最近花了点时间认真看了智能指针,特地来写这篇文章. 1.智能指针是什么 简单来说,智能指针是一个类,它对普 ...
- 【Python】引用计数
一.概述 要保持追踪内存中的对象,Python使用了引用计数这一简单的技术. 二.引用计数的增减 2.1 增加引用计数 当对象被创建并(将其引用)赋值给变量时,该对象的引用计数被设置为1. 对象的引用 ...
- iOS开发--引用计数与ARC
以下是关于内存管理的学习笔记:引用计数与ARC. iOS5以前自动引用计数(ARC)是在MacOS X 10.7与iOS 5中引入一项新技术,用于代替之前的手工引用计数MRC(Manual Refer ...
- Objective-C内存管理之-引用计数
本文会继续深入学习OC内存管理,内容主要参考iOS高级编程,Objective-C基础教程,疯狂iOS讲义,是我学习内存管理的笔记 内存管理 1 内存管理的基本概念 1.1 Objective-C中的 ...
- 第3月第2天 find symbolicatecrash 生产者-消费者 ice 引用计数
1.linux find export find /Applications/Xcode.app/ -name symbolicatecrash -type f export DEVELOPER_DI ...
- swif-自动引用计数
import UIKit /* class Person { let name: String //强引用 init(name: String) { self.name = name print(&q ...
- OC中的自动引用计数
目录: 1,自动引用计数的定义 2,强引用和弱引用 3,类比手动引用 4,循环引用 5,CoreFoundation 内容: 自动引用计数的定义: (Automatic Reference Count ...
随机推荐
- U盘装系统系列二—-如何设置U盘启动
老毛桃U盘启动制作好之后,如何设置U盘启动呢?我的是华硕的电脑,开机后按F2进入BIOS设置(不同主板可能不一样,比如有的是按向下键或者Del键,可以在网上查下看看),按Tab键选中Boot:按向下键 ...
- 创建DataTable并把列默认值
DataTable dt=new DataTable(); dt.Columns.Add("id"); dt.Columns["id"].DefaultValu ...
- vmware安装Linux时无法打开xpdf
vmware10+redhat9 在装第二张镜像文件时,出现如下提示:无法打开xpdf-2.01-8软件包...... 解决方法: vmware中,虚拟机->设置->硬件->CD/D ...
- python学习第十四天 -面向对象编程基础
python也是支持面向对象编程的.这一章节主要讲一些python面向对象编程的一些基础. 什么是面向对象的编程? 1.面向对象编程是一种程序设计范式 2.把程序看做不同对象的相互调用 3.对现实世界 ...
- C程序设计语言练习题1-12
练习1-12 编写一个程序,以每行一个单词的行驶打印其输入. 代码如下: #include <stdio.h> // 包含标准库的信息. int main() // 定义名为main的函数 ...
- Python学习笔记总结(一)对象和流程语句总结
一.对象类型 1.数字 数字:不可变 2.字符串 字符串:不可原处修改[修改需要创建新的对象],有顺序,支持求长(len),合并(+),重复(*),索引S[0],分片(S[1:3]],成员测试(in) ...
- A + B Problem,hdu-1000
A + B Problem Problem Description Calculate A + B. Input Each line will contain two integers A and ...
- repo init 时gpg: 无法检查签名:找不到公钥
i found a solution here: http://www.marshut.com/wrrts/repo-release-1-12-4.html Sorry, I realized tod ...
- vi使用入门指南
一.Unix编辑器概述 编辑器是使用计算机的重要工具之一,在各种操作系统中,编辑器都是必不可少的部件.Unix及其相似的ix操作系统系列中,为方便各种用户在各个不同的环境中使用,提供了一系列的ex编辑 ...
- github进行修改
1)git status:可以让我们时刻掌握仓库当前的状态. 2)git diff [文件名]:查看改变的详细信息,显示的结果是Unix通用的diff格式. 步骤: 1.修改文件 2.通过git ad ...