ATL 集合类

ATL 提供了许多用于存储和访问数据的类。 决定使用哪个类取决于多个因素,包括:

  • 要存储的数据量

  • 访问数据的效率与性能

  • 按索引或按键访问数据的能力

  • 数据的排序方式

  • 个人首选项

小型集合类

ATL 提供以下数组类来处理少量对象。 但是,这些类是有限的,旨在供 ATL 内部使用。 不建议在程序中使用这些类。

数据存储的类型
CSimpleArray 实现用于处理少量对象的数组类。
CSimpleMap 实现用于处理少量对象的映射类。

常规用途集合类

以下类实现数组、列表和映射,并作为常规用途集合类提供:

数据存储的类型
CAtlArray 实现数组。
CAtlList 实现列表。
CAtlMap 实现映射结构,其中可以通过键或值引用数据。
CRBMap 使用 Red-Black 算法实现映射结构。
CRBMultiMap 实现 Red-Black 多映射结构。

在调试生成中使用时,这些类将捕获许多编程错误,但出于性能考虑,不会在零售版本中执行这些检查。

专用集合类

还提供了更专门的集合类来管理内存指针和接口指针:

目的
CAutoPtrArray 提供在构造智能指针数组时有用的方法。
CAutoPtrList 提供在构造智能指针列表时有用的方法。
CComUnkArray 存储 IUnknown 指针,设计为用作 IConnectionPointImpl 模板类的参数。
CHeapPtrList 提供在构造堆指针列表时有用的方法。
CInterfaceArray 提供在构造 COM 接口指针数组时有用的方法。
CInterfaceList 提供在构造 COM 接口指针列表时有用的方法。

选择集合类

每个可用的集合类提供不同的性能特征,如下表所示。

  • 列 2 和 3 描述了每个类的排序和访问特征。 在表中,术语“决定顺序”是指插入和删除项的顺序决定其在集合中的顺序;不是指项在其内容中的排序。 术语“索引检索”是指集合中的项可通过整数索引进行检索,这与典型数组中的项很相似。

  • 列 4 和 5 描述了每个类的性能。 在需要多次插入集合的应用程序中,插入速度可能特别重要;而对于其他应用程序,查找速度可能更为重要。

  • 列 6 描述了每个形状是否允许重复元素。

  • 给定集合类操作的性能根据完成操作所需的时间与集合中的元素数之间的关系来表示。 随着元素数量的增加,操作花费的时间会线性增加,这一操作被描述为 O (n) 算法。 相反,随着元素数量的增加,操作花费的时间增加得越来越少,这一操作被描述为 O(log n) 算法。 因此,在性能方面,随着元素数量增加,O(log n) 算法越来越优于 O (n) 算法。

Collection Shape Features(集合形状特征)

形状 已订购 已编入索引 插入

element
搜索

指定的元素
重复

元素
列表​​ 快速(常量时间) 慢速 O(n)
数组 按 int(常量时间) 慢速 O(n),除非在末尾插入,在这种情况下为常量时间 慢速 O(n)
Map 按键(常量时间) 快速(常量时间) 快速(常量时间) 否(键)是(值)
Red-Black 映射 是(按键) 按键 O(log n) 快速 O(log n) 快速 O(log n)
Red-Black 多映射 是(按键) 按键 O(log n)(每个键有多个值) 快速 O(log n) 快速 O(log n) 是(每个键多个值)

使用 CTraits 对象

由于 ATL 集合类可用于存储各种用户定义的数据类型,因此可将其用于替代重要函数(如比较函数)。 这是使用 CTraits 类实现的。

CTraits 类与 MFC 集合类帮助程序函数类似,但更灵活;有关详细信息,请参阅集合类帮助程序

构造集合类时,可以选择指定 CTraits 类。 此类将包含代码,这些代码将在由构成集合类的其他方法调用时执行比较等操作。 例如,如果列表对象包含自己的用户定义结构,则可能需要重新定义相等性测试以仅比较某些成员变量。 这样,列表对象的 Find 方法将以更有效的方式运行。

示例

代码

// Collection class / traits class example.
// This program demonstrates using a CTraits class
// to create a new comparison operator.

#define MAX_STRING 80

// Define our own data type to store in the list.

struct MyData 
{
   int ID;
   TCHAR name[MAX_STRING];
   TCHAR address[MAX_STRING];
};

// Define our own traits class, making use of the
// existing traits and overriding only the comparison
// we need.

class MyTraits : public CElementTraits< MyData >
{
public:
    // Override the comparison to only compare
    // the ID value.

   static bool CompareElements(const MyData& element1, const MyData& element2)
   {
      if (element1.ID == element2.ID)
         return true;
      else
         return false;
   };
};

void DoAtlCustomTraitsList()
{
   // Declare the array, with our data type and traits class 

   CAtlList < MyData, MyTraits > MyList;

   // Create some variables of our data type

   MyData add_item, search_item;

   // Add some elements to the list.

   add_item.ID = 1;
   _stprintf_s(add_item.name, _T("Rumpelstiltskin"));
   _stprintf_s(add_item.address, _T("One Grimm Way"));

   MyList.AddHead(add_item);

   add_item.ID = 2;
   _stprintf_s(add_item.name, _T("Rapunzel"));
   _stprintf_s(add_item.address, _T("One Grimm Way"));

   MyList.AddHead(add_item);

   add_item.ID = 3;
   _stprintf_s(add_item.name, _T("Cinderella"));
   _stprintf_s(add_item.address, _T("Two Grimm Way"));

   MyList.AddHead(add_item);

   // Create an element which will be used
   // to search the list for a match.

   search_item.ID = 2;
   _stprintf_s(search_item.name, _T("Don't care"));
   _stprintf_s(search_item.address, _T("Don't care"));

   // Perform a comparison by searching for a match
   // between any element in the list, and our
   // search item. This operation will use the
   // (overridden) comparison operator and will
   // find a match when the IDs are the same.

   POSITION i;

   i = MyList.Find(search_item);

   if (i != NULL)
      _tprintf_s(_T("Item found!\n"));
   else
      _tprintf_s(_T("Item not found.\n"));
}

注释

有关 CTraits 类的列表,请参阅集合类

下图显示了 CTraits 类的类层次结构。

Diagram that shows the traits hierarchy for collection classes.

集合类示例

以下示例演示了集合类:

另请参阅

概念
集合类