ACE篇之五:ACE容器之一(双向链表)

来源:互联网 发布:食品安全网络谣言 编辑:程序博客网 时间:2024/05/17 10:27

http://hi.baidu.com/qingshanyin/blog/item/4c487e50c740f8648535249e.html

前沿:为了跨平台的需要,以及性能考虑,ACE创建了自己的容器。ACE支持两种容器:基于模板的、类型安全的容器,以及基于对象的容器。

基于模板的容器:允许在编译时创建“针对特定类型的容器”;基于对象的容器:支持某一类对象类型的插入和删除。

ACE的容器包含两类:序列容器和关联容器。

序列容器是一种其元素按照线性顺序排列的容器。由于要在容器中进行迭代,各个元素的顺序不会改变。列表、栈、队列、数组和集合都是ACE的一些类所代表的序列的例子。

1、双向链表

双向链表在序列中同时维护有向前和向后的链接,从而可以在序列中进行高效的向前和向后遍历。但不能对元素进行随机访问。

ACE_DLList是ACE提供的双向链表。它是一个基于模板的容器,所以我们需要预先指定我们的列表中使用的元素的类型。

2、双向链表测试代码

(1)双向链表元素定义:DataElement(DataElement.h)

//DataElement元素有一个很好的特性:即它会记住自己现在有多少个实例
//双向链表测试,以下定义的是链表元素类型
class DataElement
{
friend class DataElementEx;


public:
DataElement(){count_++;}

DataElement(int data):data_(data){count_++;}

DataElement(const DataElement& e)
{
   data_=e.getData();
   count_++;
}
DataElement& operator=(const DataElement& e)
{
   data_=e.getData();
   return *this;
}
bool operator==(const DataElement& e)
{
   return this->data_==e.data_;
}

~DataElement(){count_--;}

int getData(void)const{return data_;}

void setData(int val){data_=val;}

static int numOfActiveObjects(void){return count_;}

private:
int data_;
static int count_;
};
(2)测试类定义:ListTests(ListTests.h)

#pragma once
#include "ace/Containers.h"
#include "DataElement.h"
//双向链表测试
//双向链表支持前向和后向迭代
typedef ACE_DLList<DataElement> MyList;//该容器可以存储元素对象,也可以存储指向对象的指针
class ListTests
{
public:
ListTests(void);
~ListTests(void);
int run(void);

// 显示列表
void displayList(MyList& list);
// 销毁对象
void destoryList(MyList& list);
};
(3)测试类实现(ListTests.cpp)

#define ACE_NTRACE 0

#include "ListTests.h"
int DataElement::count_=0;//必须对静态成员进行初始化
ListTests::ListTests(void)
{
}

ListTests::~ListTests(void)
{
}

int ListTests::run(void)
{
ACE_TRACE (ACE_TEXT("ListTest::run"));

//创建一个列表,插入100个元素
MyList list1;
for(int i=0;i<100;i++)
{
   DataElement *element;
   ACE_NEW_RETURN(element,DataElement(i),-1);

   //注意:存放在容器里面的是指向元素的指针,而不是元素本身
   //这意味着,当列表出作用域时候,需要负责删除元素本身,否则数据元素将
   //在堆上继续存在,否则会造成内存泄漏
   list1.insert_tail(element);
}
//迭代显示列表
this->displayList(list1);
ACE_DEBUG((LM_DEBUG,ACE_TEXT("#of live objects:%d/n"),DataElement::numOfActiveObjects()));
//从调试情况来看,数目为100
//创建list1的一个拷贝
MyList list2;
list2=list1;//此处为浅拷贝
//迭代显示拷贝列表的内容
this->displayList(list2);
ACE_DEBUG((LM_DEBUG,ACE_TEXT("#of live objects:%d/n"),DataElement::numOfActiveObjects()));
//从调试情况来看,对象数目仍然是100
//清除拷贝列表和其所有元素
//因为两个列表有相同的元素,
//这将导致list1包含的指针所指向的数据元素已经被销毁。
this->destoryList(list2);

ACE_DEBUG((LM_DEBUG,ACE_TEXT("#of live objects:%d/n"),DataElement::numOfActiveObjects()));
//从调试情况来看,对象数目为0

//所有列表本身将在此被清理。注:列表析构函数将销毁任何列表拷贝,无论其包含什么数据
//因为在这种情况下,列表包含指向数据元素的指针,此处是销毁这些数据元素的唯一机会。
return 0;
}

// 使用迭代器,显示列表
void ListTests::displayList(MyList& list)
{
ACE_TRACE(ACE_TEXT("ListTest::displayList"));
ACE_DEBUG((LM_DEBUG,ACE_TEXT("Forword iteration/n")));
//前向迭代器
ACE_DLList_Iterator<DataElement> iter(list);
while(!iter.done())
{
   ACE_DEBUG((LM_DEBUG,ACE_TEXT("%d:"),iter.next()->getData()));
   iter++;
}
ACE_DEBUG((LM_DEBUG,ACE_TEXT("/n")));

ACE_DEBUG((LM_DEBUG,ACE_TEXT("Reverse Iteration /n")));

//后向迭代器
ACE_DLList_Reverse_Iterator<DataElement> riter(list);
while(!riter.done())
{
   ACE_DEBUG((LM_DEBUG,ACE_TEXT("%d:"),riter.next()->getData()));
   riter++;
}
ACE_DEBUG((LM_DEBUG,ACE_TEXT("/n")));
}

// 销毁对象
void ListTests::destoryList(MyList& list)
{
ACE_DLList_Iterator<DataElement> iter(list);
while(!iter.done())
{
   delete iter.next();//析构元素,避免内存泄漏
   iter++;
}
}

(4)入口函数

// Container_Practice.cpp : 定义控制台应用程序的入口点。
//
#define ACE_NTRACE 0

#include "ace/Containers.h"
#include "ListTests.h"
typedef ACE_DLList<DataElement>MyList;
int ACE_TMAIN(int argc, ACE_TCHAR* argv[])
{
ListTests listtest;
listtest.run();

return 0;
}

原创粉丝点击