C++侵入式链表
C++标准模板库中的list是非侵入式的链表,当我们通过对象来删除容器中的对象时,需要从头到尾查找一次得到iterator,最后通过iterator来删除对象。这样删除容器中的对象时比较缓慢,所以就实现了一个侵入式链表。
intrusive_list.h
#ifndef _Intrusive_List_H_
#define _Intrusive_List_H_ // 侵入式链表
template<class T>
class intrusive_list {
public:
struct Node;
// 迭代器
class iterator {
public:
iterator(Node* node) : m_node(node) {} iterator& operator ++() {
if (m_node)
m_node = m_node->m_next;
return *this;
}
iterator& operator --() {
if (m_node)
m_node = m_node->m_prev;
return *this;
} bool operator == (const iterator& iter) { return m_node == iter.m_node; }
bool operator != (const iterator& iter) { return !operator ==(iter); } T& operator *() { return *m_node; }
T* operator ->() { return m_node; } private:
Node* m_node;
}; intrusive_list() : m_head(nullptr), m_tail(nullptr) {} ~intrusive_list() {
Node* node = m_head;
while (node) {
Node* next = node->m_next;
delete node;
node = next;
}
} // 添加对象
template<class... Args>
T* add(Args... args) {
Node* node = new Node(args...); if (m_head && m_tail) {
node->m_prev = m_tail;
m_tail->m_next = node;
m_tail = node;
}
else {
m_head = node;
m_tail = node;
}
return node;
} // 移除对象
void remove(T* ptr) {
Node* node = (Node*)ptr;
assert(node->m_valid);
if (m_head == node) {
m_head = m_head->m_next;
}
if (m_tail == node) {
m_tail = m_tail->m_prev;
}
if (node->m_prev)
node->m_prev->m_next = node->m_next;
if (node->m_next)
node->m_next->m_prev = node->m_prev;
delete node;
} iterator begin() { return iterator(m_head); }
iterator end() { return iterator(nullptr); } private:
struct Node : public T {
template<class... Args>
Node(Args... args) : T(args...), m_valid(true), m_prev(nullptr), m_next(nullptr) {} bool m_valid;
Node* m_prev;
Node* m_next;
}; Node* m_head;
Node* m_tail;
}; #endif
test.cpp
int _tmain(int argc, _TCHAR* argv[])
{
struct Person {
Person(const char* name) : m_name(name) {} std::string m_name;
int m_age;
}; intrusive_list<Person> lst; Person* p0 = lst.add("");
lst.add("");
lst.add("");
lst.add("");
lst.add("");
Person* p1 = lst.add(""); lst.remove(p0);
lst.remove(p1); for (auto iter = lst.begin(); iter != lst.end(); ++iter) {
std::cout << iter->m_name << std::endl;
} return ;
}
C++侵入式链表的更多相关文章
- 侵入式单链表的简单实现(cont)
前一节介绍的侵入式链表实现在封装性方面做得不好,因为会让消费者foo.c直接使用宏container_of().这一节对list的定义做了一点改进,如下所示: typedef struct list_ ...
- BlockCanary 一个轻量的,非侵入式的性能监控组件(阿里)
开发者博客: BlockCanary — 轻松找出Android App界面卡顿元凶 开源代码:moduth/blockcanary BlockCanary对主线程操作进行了完全透明的监控,并能输出有 ...
- Android沉浸式(侵入式)标题栏(状态栏)Status(三)
Android沉浸式(侵入式)标题栏(状态栏)Status(三) 从附录文章1,2可以看到,依靠Android系统提供的标准方案,状态栏即便在透明状态下,仍然有些半透明而不是全透明.本文是And ...
- Android沉浸式(侵入式)标题栏(状态栏)Status(二)
Android沉浸式(侵入式)标题栏(状态栏)Status(二) 附录1以xml写style实现了Android沉浸式(侵入式)状态栏(标题栏),同样以上层Java代码实现.在附录文章1的基础上 ...
- Android沉浸式(侵入式)标题栏(状态栏)Status(一)
Android沉浸式(侵入式)标题栏(状态栏)Status(一) 现在越来越多的APP设计采用这种称之为沉浸式状态栏(Status)的设计,这种沉浸式状态栏又称之"侵入式"状 ...
- Hook 无侵入式埋点(页面统计)
一.技术原理 Method-Swizzling 黑魔法 方法交换(不懂的可以查) 二.页面统计 某盟页面统计SDK需要开发者在APP基类里实现ViewDidAppear和viewDidDisappea ...
- 应用调试(五)侵入式SWI
目录 应用调试(五)侵入式SWI 场景应用 测试程序 修改APP的bin 修改SWI 获得当前进程的寄存器 测试运行 恢复代码 进程间内存拷贝 TODO 更多参考文献 title: 应用调试(五)侵入 ...
- 使用phpAnalysis打造PHP应用非侵入式性能分析器
使用phpAnalysis打造PHP应用非侵入式性能分析器,查找PHP性能瓶颈. 什么是phpAnalysis phpAnalysis是一款轻量级非侵入式PHP应用性能分析器,适用于开发.测试及生产环 ...
- Spring学习(1):侵入式与非侵入式,轻量级与重量级
一. 引言 在阅读spring相关资料,都会提到Spring是非侵入式编程模型,轻量级框架,那么就有必要了解下这些概念. 二. 侵入式与非侵入式 非侵入式:使用一个新的技术不会或者基本不改变原有代码结 ...
随机推荐
- 跳转到设置页面 与appstory
//MARK:系统跳到应用设置页面 func systemMySet(){ let url = NSURL(string: UIApplicationOpenSettingsURLString) if ...
- js string 转 int 注意的问题——parseInt
< script > var str = '1250';alert(Number(str)); //得到1250 alert(parseInt(str)); //得到1250 var st ...
- STM32F103的11个定时器详解(转)
源:STM32F103的11个定时器详解 STM32F103系列的单片机一共有11个定时器,其中:2个高级定时器4个普通定时器2个基本定时器2个看门狗定时器1个系统嘀嗒定时器 出去看门狗定时器和系统滴 ...
- jQuery EasyUI的使用入门
jQuery EasyUI不是什么太高级的东西,就是用jQuery写了很多方法.定义了很多属性,通过调用这些方法.属性,可以达到一些特定的效果,然后我们再根据具体需求微调就好了.至少需要导入两个样式表 ...
- <button>与<input type="button"> 的区别
<button> button按钮点击会刷新整个页面 <input type="button"> 不会刷新整个页面 本文为本人用来记录自己做的一些东西,如 ...
- 郑州尚学堂:链表的C语言如何实现动态内存分配
一.为什么用动态内存分配 但我们未学习链表的时候,如果要存储数量比较多的同类型或同结构的数据的时候,总是使用一个数组.比如说我们要存储一个班级学生的某科分数,总是定义一个float型(存在0.5分)数 ...
- c# windows服务 一个项目安装多个服务
创建windows服务就不讲解了,其它大神写太多了.这里只写一个项目安装多个服务的教程.如:http://www.cnblogs.com/zzgblog/p/4595839.html 首先按下图创建多 ...
- MySQL导入乱码解决
导入时出现乱码,需要在语句中添加指定导入数据的编码格式: mysql -uroot -p database_name < database_backup.sql --default-charac ...
- mysql 初始化修改密码问题(Mac系统)
今天公司大牛帮我搞定了mysql初始化密码问题,纪录一下: ~ ps aux | grep mysqlMetro 7149 0.0 0.0 2432772 564 s000 R+ 7:16下午 0:0 ...
- PostgreSQL 类型转换 -除法
PostgreSQL 类型转换 类似Oracle ,PostgreSQL也有强大的类型转换函数, 下面仅举两个类型转换例子. --1 例子 postgres=# select 1/4; ?colum ...