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是非侵入式编程模型,轻量级框架,那么就有必要了解下这些概念. 二. 侵入式与非侵入式 非侵入式:使用一个新的技术不会或者基本不改变原有代码结 ...
随机推荐
- [Q]pdfFactory打印机内存不能为read的问题
运行环境:xp系统,AutoCAD2007 1. 使用pdfFactory打印文本文件没有问题. 2. 使用CAD打印的时候出现问题,使用CAD自带的PLOT命令打印也出现相同的问题. 3. 使用相同 ...
- 在GNU/Linux下设置与定时更换桌面壁纸
1 简介 在电脑桌面设置一组可以定时更换的壁纸已经不是什么新奇的功能了.比如,Windows 7.KDE桌面环境都可以实现这样的效果.可是,自己目前使用的Debian系统并未安装KDE.GNOME这样 ...
- javabean解决jsp中中文乱码问题
问题描述:useBean行为定义了Java Bean对象(Person类包括姓名[string],年龄[int]),使用html页面向JSP页面提交数据,JSP页面中使用Java Bean行为来处理提 ...
- ntp升级
1. 系统与软件版本 1.1 系统版本 CentOS6.5 x86_64 1.2 ntpd软件版本 ntp-4.2.8p9.tar.gz 1.3 下载地址 官方下载地址:http://support. ...
- Byte Array to Hexadecimal String
Lookup Text: 23,879.41 (20.8X faster) Sentence: 1.15 (23.9X faster) /// <summary> /// Hex stri ...
- drupal7 修改文件上传大小限制
参考文章:Drupal 7 设置上传文件的限制大小 自己用 '#type' => 'managed_file'做了一个上传的功能,但是上传时总是说超过了2M的限制,接下来说一下怎么修改限制. 一 ...
- workerman简单例子
workerman下载地址 http://www.workerman.net/ html <!DOCTYPE html> <html> <head> <tit ...
- centos7下安装JDK 1.7
选则64位的rpm包下载:jdk-7u25-linux-x64.rpmrpm –ivh 'jdk安装包路径' 环境变量配置 # exportJAVA_HOME=<jdk-install-dir& ...
- 统计C语言程序行数
补充前一篇中统计C语言程序行数的程序 写得比较匆忙,可能有些失误,等弄明白GitHub的用法并完善程序后再补充完整代码链接 没有写成函数,但经过简单修改可以作为一个计算或判断函数使用 判断算法主要为以 ...
- Effective JavaScript :第一章
第一章 一.严格模式与非严格模式 1.在程序中启用严格模式的方式是在程序的最开始增加一个特定的字符串字面量: ‘use strict’ 同样可以在函数体的开始处加入这句指令以启用该函数的严格模式. f ...