ACE容器,现行数组,双向链表

来源:互联网 发布:软件界面图标设计 编辑:程序博客网 时间:2024/05/02 15:28

ACE容器

ACE也提供了好多易用的容器类,其中包括队列、链表、HASH表、堆栈等。当然C++ STL已经拥有大量的优秀的容器供我们使用,但是据说ACE的容器效率更高耗费内存更少。当我们的系统资源比较紧缺时ACE的容器仍然是一个不错的选择(比如做嵌入式开发的时候)。

容器测试数据元素

DataElement作为我们测试容器的一个简单的数据类型,在其中封装了一个整形变量。DataElement有一个很好的特性它会记住现在有多少个实例,下面的测试用例将利用这一特性说明数据元素的生命周期。

DataElement.h

/* -*- C++ -*- */
// DataElement.h,v 1.2 2005/04/23 05:52:26 ossama Exp
 
#if !defined(DATAELEMENT_H)
#define DATAELEMENT_H
 
class DataElementEx;
 
// Listing 1 code/ch05
// A simple data element class.
class DataElement
{
  friend class DataElementEx;
 
public:
  DataElement () : data_ (0) { 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_;
};
// Listing 1
 
int DataElement::count_ = 0;
 
#endif /*DATAELEMENT_H*/
 

线性数组

线性数组是最简单的一种数据结构,ACE通过ACE_Array模板容器实现了对线性数组的封装。

示例代码

Array.cpp

此示例演示了ACE_Array容器的使用,包括了容器的比较、拷贝和通过迭代器对数据元素的遍历
// Array.cpp,v 1.3 2004/01/05 22:57:06 shuston Exp
 
#include "ace/OS_Memory.h"
#include "ace/Log_Msg.h"
// Listing 1 code/ch05
#include "ace/Containers.h"
#include "DataElement.h"
 
int ACE_TMAIN (int, ACE_TCHAR *[])
{
  //初始化数组并为其分配存储空间,在此数组存储的是指针。
  ACE_Array<DataElement*> arr (10);
  DataElement *elem = 0;
  // Allocate and insert elements.
  for (int i = 0; i < 10; i++)
    {
      ACE_NEW_RETURN (elem, DataElement (i), -1);
      arr[i] = elem;
    }
 
  // Checked access.
  ACE_ASSERT (arr.set (elem, 11) == -1);
  ACE_ASSERT (arr.get (elem, 11) == -1);
 
  // Make a copy and compare to the original.
  ACE_Array<DataElement*> copy = arr;
  ACE_ASSERT (copy == arr);
  //通过迭代器对数组遍历
  ACE_Array<DataElement*>::ITERATOR iter (arr);
  while (!iter.done ())
    {
      DataElement** data;
      iter.next (data);
      ACE_DEBUG ((LM_DEBUG,
                  ACE_TEXT ("%d/n"), (*data)->getData ()));
      delete (*data);
      iter.advance ();
    }
  return 0;
}
// Listing 1
 
#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
template class ACE_Array <DataElement*>;
template class ACE_Array_Base<DataElement*>;
template class ACE_Array_Iterator<DataElement*>;
#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
#pragma instantiate ACE_Array <DataElement*>
#pragma instantiate ACE_Array_Base<DataElement*>
#pragma instantiate ACE_Array_Iterator<DataElement*>
#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION*/

执行结果

D:/project/ACE_wrappers/examples/APG/Containers>Array
0
1
2
3
4
5
6
7
8
9

双向链表


双向链表在序列中维护向前和向后的链接,从而可以进行高效的向前和向后遍历。由于链表的序列不是线性的所以不能够随机访问。ACE_DLList模板容器实现了双向链表的功能。和其他大多数容器不同的是,ACE_DLList是一个引用容器而不是值容器,它存储的只是对象元素的引用而不是值的副本。这样在超出ACE_DLList实例变量的作用域时如果不对其内元素的引用进行手动删除就会造成内存泄漏。

代码示例

DLList.cpp

此示例演示了通过ACE_DLList模板类对链表进行的插入、删除、迭代操作。
// DLList.cpp,v 1.2 2004/01/05 22:57:06 shuston Exp
 
#include "ace/OS_Memory.h"
#include "ace/Log_Msg.h"
 
// Listing 1 code/ch05
#include "ace/Containers.h"
#include "DataElement.h"
 
// Create a new type of list that can store only DataElements.
typedef ACE_DLList<DataElement> MyList;
// Listing 1
 
// Listing 2 code/ch05
class ListTest
{
public:
  int run (void);
  void displayList (MyList & list); // Display all elements.
  void destroyList (MyList& list);  // Destroy all elements.
};
// Listing 2
// Listing 3 code/ch05
int
ListTest::run (void)
{
  ACE_TRACE (ACE_TEXT ("ListTest::run"));
 
  // Create a list and insert 100 elements.
  MyList list1;
  //在链表尾部插入100个元素的指针引用
  for (int i = 0; i < 100; i++)
    {
      DataElement *element;
      ACE_NEW_RETURN (element, DataElement (i), -1);
      list1.insert_tail (element);
    }
 
  // Iterate through and display to output.
  this->displayList (list1);
 
  //创建链表实例list2并拷贝list1的内容。由于list1list2存储的都是对象元素的引用(都是指向相同的内存区域)
  //所以在后面调用对list2调用destroyList 方法时实际上是释放了所有对象元素。
  MyList list2;
  list2 = list1;
 
  // Iterate over the copy and display it to output.
  this->displayList(list2);
 
  // Get rid of the copy list and all its elements.
  // Since both lists had the *same* elements
  // this will cause list1 to contain pointers that
  // point to data elements that have already been destroyed!
  this->destroyList (list2);
 
  //DataElement对象元素已经被释放其实例的引用应该是0
  ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("# of live objects: %d/n"),
              DataElement::numOfActiveObjects()));
 
  // The lists themselves are destroyed here. Note that the
  // list destructor will destroy copies of whatever data the
  // list contained. Since in this case the list contained
  // copies of pointers to the data elements these are the
  // only thing that gets destroyed here.
  return 0;
}
// Listing 3
// Listing 4 code/ch05
//手动的对内部引用数据元素进行释放
void
ListTest::destroyList (MyList& list)
{
  ACE_TRACE (ACE_TEXT ("ListTest::destroyList"));
 
  ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Destroying data elements/n")));
 
  // Iterate through and delete all the data elements on the list.
  for (ACE_DLList_Iterator<DataElement> iter (list);
       !iter.done ();
       iter++)
    {
      DataElement *de = iter.next ();
      delete de;
    }
}
// Listing 4
// Listing 5 code/ch05
//通过迭代器分别从正向和反向迭代对链表中的数据元素进行遍历
void
ListTest::displayList (MyList& list)
{
  ACE_TRACE (ACE_TEXT ("ListTest::displayList"));
 
  ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Forward 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")));
}
// Listing 5
int ACE_TMAIN (int, ACE_TCHAR *[])
{
  ListTest test;
  return test.run ();
}
 
#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
template class ACE_DLList <DataElement>;
template class ACE_DLList_Iterator <DataElement>;
template class ACE_DLList_Reverse_Iterator <DataElement>;
template class ACE_Double_Linked_List<ACE_DLList_Node>;
template class ACE_Double_Linked_List_Iterator_Base<ACE_DLList_Node>;
#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
#pragma instantiate ACE_DLList <DataElement>
#pragma instantiate ACE_DLList_Iterator <DataElement*>
#pragma instantiate ACE_DLList_Reverse_Iterator <DataElement*>
#pragma instantiate ACE_Double_Linked_List<ACE_DLList_Node>;
#pragma instantiate ACE_Double_Linked_List_Iterator_Base<ACE_DLList_Node>;
#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION*/

执行结果

 
D:/project/ACE_wrappers/examples/APG/Containers>DLList
Forward iteration
0:1:2:3:4:5:6:7:8:9:10:11:12:13:14:15:16:17:18:19:20:21:22:23:24:25:26:27:28:29:
30:31:32:33:34:35:36:37:38:39:40:41:42:43:44:45:46:47:48:49:50:51:52:53:54:55:56
:57:58:59:60:61:62:63:64:65:66:67:68:69:70:71:72:73:74:75:76:77:78:79:80:81:82:8
3:84:85:86:87:88:89:90:91:92:93:94:95:96:97:98:99:
Reverse Iteration
99:98:97:96:95:94:93:92:91:90:89:88:87:86:85:84:83:82:81:80:79:78:77:76:75:74:73
:72:71:70:69:68:67:66:65:64:63:62:61:60:59:58:57:56:55:54:53:52:51:50:49:48:47:4
6:45:44:43:42:41:40:39:38:37:36:35:34:33:32:31:30:29:28:27:26:25:24:23:22:21:20:
19:18:17:16:15:14:13:12:11:10:9:8:7:6:5:4:3:2:1:0:
Forward iteration
0:1:2:3:4:5:6:7:8:9:10:11:12:13:14:15:16:17:18:19:20:21:22:23:24:25:26:27:28:29:
30:31:32:33:34:35:36:37:38:39:40:41:42:43:44:45:46:47:48:49:50:51:52:53:54:55:56
:57:58:59:60:61:62:63:64:65:66:67:68:69:70:71:72:73:74:75:76:77:78:79:80:81:82:8
3:84:85:86:87:88:89:90:91:92:93:94:95:96:97:98:99:
Reverse Iteration
99:98:97:96:95:94:93:92:91:90:89:88:87:86:85:84:83:82:81:80:79:78:77:76:75:74:73
:72:71:70:69:68:67:66:65:64:63:62:61:60:59:58:57:56:55:54:53:52:51:50:49:48:47:4
6:45:44:43:42:41:40:39:38:37:36:35:34:33:32:31:30:29:28:27:26:25:24:23:22:21:20:
19:18:17:16:15:14:13:12:11:10:9:8:7:6:5:4:3:2:1:0:
Destroying data elements
# of live objects: 0