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++侵入式链表的更多相关文章

  1. 侵入式单链表的简单实现(cont)

    前一节介绍的侵入式链表实现在封装性方面做得不好,因为会让消费者foo.c直接使用宏container_of().这一节对list的定义做了一点改进,如下所示: typedef struct list_ ...

  2. BlockCanary 一个轻量的,非侵入式的性能监控组件(阿里)

    开发者博客: BlockCanary — 轻松找出Android App界面卡顿元凶 开源代码:moduth/blockcanary BlockCanary对主线程操作进行了完全透明的监控,并能输出有 ...

  3. Android沉浸式(侵入式)标题栏(状态栏)Status(三)

     Android沉浸式(侵入式)标题栏(状态栏)Status(三) 从附录文章1,2可以看到,依靠Android系统提供的标准方案,状态栏即便在透明状态下,仍然有些半透明而不是全透明.本文是And ...

  4. Android沉浸式(侵入式)标题栏(状态栏)Status(二)

     Android沉浸式(侵入式)标题栏(状态栏)Status(二) 附录1以xml写style实现了Android沉浸式(侵入式)状态栏(标题栏),同样以上层Java代码实现.在附录文章1的基础上 ...

  5. Android沉浸式(侵入式)标题栏(状态栏)Status(一)

     Android沉浸式(侵入式)标题栏(状态栏)Status(一) 现在越来越多的APP设计采用这种称之为沉浸式状态栏(Status)的设计,这种沉浸式状态栏又称之"侵入式"状 ...

  6. Hook 无侵入式埋点(页面统计)

    一.技术原理 Method-Swizzling 黑魔法 方法交换(不懂的可以查) 二.页面统计 某盟页面统计SDK需要开发者在APP基类里实现ViewDidAppear和viewDidDisappea ...

  7. 应用调试(五)侵入式SWI

    目录 应用调试(五)侵入式SWI 场景应用 测试程序 修改APP的bin 修改SWI 获得当前进程的寄存器 测试运行 恢复代码 进程间内存拷贝 TODO 更多参考文献 title: 应用调试(五)侵入 ...

  8. 使用phpAnalysis打造PHP应用非侵入式性能分析器

    使用phpAnalysis打造PHP应用非侵入式性能分析器,查找PHP性能瓶颈. 什么是phpAnalysis phpAnalysis是一款轻量级非侵入式PHP应用性能分析器,适用于开发.测试及生产环 ...

  9. Spring学习(1):侵入式与非侵入式,轻量级与重量级

    一. 引言 在阅读spring相关资料,都会提到Spring是非侵入式编程模型,轻量级框架,那么就有必要了解下这些概念. 二. 侵入式与非侵入式 非侵入式:使用一个新的技术不会或者基本不改变原有代码结 ...

随机推荐

  1. vga显示彩条

    vga显示驱动程序可分为扫描行列和行列同步两个部分 //注意:只有在有效区域内给vga赋值才会有颜色变化 assign vga_b = isready ? vga_s[:] :'d0; assign ...

  2. js将xml对象,xml文件解析成xml dom对象,来对对象进行操作

    由于ie与其他的浏览器对于xml文件的解析方式不同,所以有不同的解析方式 1.1 IE解析xml文件的方式 var xmlDoc=new ActiveXObject("Microsoft.X ...

  3. jQuery的9中构造函数

    // 接受一个字符串,其中包含了用于匹配元素集合的 CSS 选择器 jQuery([selector,[context]]) // 传入单个 DOM jQuery(element) // 传入 DOM ...

  4. C#中值类型与引用类型通俗理解

    关于值类型和引用类型已经有很多人写了很多文章,但是很多人也只是停留在字面上的理解,如果采用一种通俗的方法来解释,想必很多人都会理解.我们都知道值类型存储在栈上,引用类型存储在堆上,引用类型都是xxx类 ...

  5. Restful随笔

    Rest,即Resources Representational State Transfer(资源表现层状态转化). ·资源(Resources),网络上的一个实体,每种资源对应一个特定的URI(统 ...

  6. spring可以get到bean,注入却为空

    使用spring的时候,已经将要用的bean注入到容器之中却发现在程序中总是报null,后来发现是因为当前的启动类没有在容器之中,所以用上下文可以get到,但是注入却无效

  7. Space Shooter

    项目:https://pan.baidu.com/s/1jIDe2H4 using UnityEngine; using System.Collections; namespace VoidGame ...

  8. javascript初始笔记

    1.在html中使用点击事件: <button type="button" onclick="myclick()">click me<butt ...

  9. python-cmp()的使用

    注意:python3中已经删除了cmp()该函数. cmp(x,y) 比较x与y,当x>y时,返回1: 当x==y时,返回0: 当x<y时,返回-1: >>>cmp(1, ...

  10. L2-004. 这是二叉搜索树吗?

    L2-004. 这是二叉搜索树吗? 题目链接:https://www.patest.cn/contests/gplt/L2-004 这题我的方法是先递归判定是不是二叉搜索树(镜像),再建树输出. 代码 ...