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("11");
    lst.add("2");
    lst.add("3");
    lst.add("4");
    lst.add("5");
    Person* p1 = lst.add("6");

    lst.remove(p0);
    lst.remove(p1);

    for (auto iter = lst.begin(); iter != lst.end(); ++iter) {
        std::cout << iter->m_name << std::endl;
    }

    return 0;
}
时间: 2024-10-24 12:06:01

C++侵入式链表的相关文章

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

前一节介绍的侵入式链表的实现的封装性做得不好,因为会让消费者foo.c直接使用宏container_of().这一节对list的定义做了一下改进,如下所示: typedef struct list_s { struct list_s *next; size_t offset; } list_t; 既然链表结点存了offset, 那么就不再需要container_of()了.(注:Solaris的侵入式双向循环链表就是这么实现的) 1. list.h 1 #ifndef _LIST_H 2 #de

侵入式单链表的简单实现

通常情况下,单链表的定义是这样子滴, typedef struct foo_s { int data; struct foo_s *next; } foo_t; 结构体里包含了链表指针next; 而侵入式单链表却不同,让结构体包含一个通用的链表.看起来是这个样儿滴, typedef struct list_s { struct list_s *next; } list_t; typedef struct foo_s { int data; list_t link; } foo_t; 所有包含了l

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

开发者博客: BlockCanary — 轻松找出Android App界面卡顿元凶 开源代码:moduth/blockcanary BlockCanary对主线程操作进行了完全透明的监控,并能输出有效的信息,帮助开发分析.定位到问题所在,迅速优化应用.其特点有: 非侵入式,简单的两行就打开监控,不需要到处打点,破坏代码优雅性. 精准,输出的信息可以帮助定位到问题所在(精确到行),不需要像Logcat一样,慢慢去找. 目前包括了核心监控输出文件,以及UI显示卡顿信息功能.仅支持Android端.

【SSH进阶之路】一步步重构容器实现Spring框架——解决容器对组件的“侵入式”管理的两种方案--主动查找和控制反转(九)

目录 [SSH进阶之路]一步步重构容器实现Spring框架--从一个简单的容器开始(八) [SSH进阶之路]一步步重构容器实现Spring框架--解决容器对组件的"侵入式"管理的两种方案--主动查找和控制反转(九) [SSH进阶之路]一步步重构容器实现Spring框架--配置文件+反射实现IoC容器(十)(未更新) [SSH进阶之路]一步步重构容器实现Spring框架--彻底封装,实现简单灵活的Spring框架(十一)(未更新) 对于IOC的原理,我们曾经写过一篇博文,[SSH进阶之路

MVC的验证(模型注解和非侵入式脚本的结合使用)

@HtmlHrlper方式创建的标签,会自动生成一些属性,其中一些属性就是关于验证 如图示例: 模型注解 通过模型注解后,MVC的验证,包括前台客户端,后台服务器的验证,MVC统统都做了包含,即使用户在客户端禁用Javascript,服务器也会将非法操作进行验证,当前前提是针对Model实体标识了注解的情况. 要能够正常进行非空等合法性验证必须做如下步骤(前提条件): 1.必须在实体的每个类型上加上Required特性,但是数字型的属性默认已经加上了. 2.必须在视图上导入如下脚本: <scri

Spring 侵入式和非侵入式

1.非侵入式的技术体现 允许在应用系统中自由选择和组装Spring框架的各个功能模块,并且不强制要求应用系统的类必须从Spring框架的系统API的某个类来继承或者实现某个接口. 2.如何实现非侵入式的设计目标的 1)应用反射机制,通过动态调用的方式来提供各方面的功能,建立核心组间BeanFactory 2)配合使用Spring框架中的BeanWrapper和BeanFactory组件类最终达到对象的实例创建和属性注入 3)优点:允许所开发出来的应用系统能够在不用的环境中自由移植,不需要修改应用

eclipse插件安装:非侵入式方法

非侵入式安装插件方法(links安装方法) 既然有侵入式的安装,言下之意,还有个“非侵入式安装”,也有人成为links安装方法,下面看究竟是如何安装的:). 非侵入式安装也分两种,一种是绝对路径安装方法,一种是相对路径的安装方法.首先看绝对路径的安装的方法. 在上面安装过程中,我们将中文语言包NLpack1-eclipse-SDK-3.2.1-win32.zip插件解压缩到一个地方假设为F:\myplugins目录文件夹的目录结构如下: NLpack1-eclipse-SDK-3.2.1-win

Android基于AOP的非侵入式监控之——AspectJ实战

一引言 二什么是AspectJ 1 它只是一个代码编译器 2 它是用来做AOP编程的 3为什么要用AspectJ 三AspectJ原理与运用 1 基本原理 2 使用方式 21 纯注解方式 22 AspectJ语言 23 结合自定义注解使用 四AspectJ实战监听方法执行耗时打印并输出 五一些比较常见的问题 六推荐文章 一.引言 本博文的目的不是详细的介绍AspectJ的细节,而是最近项目用到了AspectJ,因此对其作了一些使用和重要概念上的总结. 相信很多做过Web的同学对AspectJ都不

侵入式和非侵入式的区别

非侵入式设计 一个客户端的代码可能包含框架功能和客户端自己的功能. 侵入式设计,就是设计者将框架功能“推”给客户端,而非侵入式设计,则是设计者将客户端的功能“拿”到框架中用. 侵入式设计有时候表现为客户端需要继承框架中的类,而非侵入式设计则表现为客户端实现框架提供的接口. 侵入式设计带来的最大缺陷是,当你决定重构你的代码时,发现之前写过的代码只能扔掉.而非侵入式设计则不然,之前写过的代码仍有价值. struts1的设计是侵入式的: public class loginAction extends