当前位置:嗨网首页>书籍在线阅读

05-大部分容器都有的成员

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

G.2 大部分容器都有的成员

所有容器都定义了表G.1列出的类型。在这个表中,x为容器类型,如vector;T为存储在容器中的类型,如int。表G.1中的示例阐明了含义

表G.1 为所有容器定义的类型

| 类型 | 值 | | :----- | :----- | :----- | :----- | | x::value-type | T,元素类型 | | x::reference | T & | | x::const_reference | const T & | | x::iterator | 指向T的迭代器类型,行为与T相似 | | x::const_iterator | 指向const T的迭代器类型,行为与const T 相似 | | x::different_type | 用于表示两个迭代器之间距离的符号整型,如两个指针的差 | | x::size_type | 无符号整型size_type可以表示数据对象的长度、元素数目和下标 |

类定义使用typedef定义这些成员。可以使用这些类型来声明适当的变量。例如,下面的代码使用迂回的方式,将由string对象组成的矢量中的第一个“bonus”替换为“bogus”,以演示如何使用成员类型来声明变量。

using namespace std;
vector<string> input;
string temp;
while (cin >> temp && temp != "quit")
    input.push_back(temp);
vector<string>::iterator want=
    find(input.begin(), input.end(), string("bonus"));
if (want != input.end())
{
    vector<string>::reference r = *want;
    r = "bogus";
}

上述代码使r成为一个指向(want指向的)input中元素的引用。同样,继续前面的例子,可以编写下面这样的代码:

vector<string>::value_type s1 = input[0]; // s1 is type string
vector<string>::reference s2 = input[1]; // s2 is type string &

这将导致s1为一个新string对象,它是input[0]的拷贝;而s2为指向input[1]的引用。在这个例子中,由于已经知道模板是基于string类型的,因此编写下面的等效代码将更简单:

string s1 = input[0];   // s1 is type string
string & s2 = input[1]; // s2 is type string &

然而,还可以在更通用的代码中使用表G.1中较精致(其中容器和元素的类型是通用的)的类型。例如,假设希望min()函数将一个指向容器的引用作为参数,并返回容器中最小的项目。这假设为用于实例化模板的值类型定义了<运算符,而不想使用STL min_element()算法,这种算法使用迭代器接口。由于参数可能是vector、list或deque,因此需要使用带模板参数(如Bag)的模板来表示容器(也就是说,Bag是一个模板类型,可能被实例化为vector、list或其他一些容器类型)。因此,函数的参数类型应为const Bag & b。返回类型是什么呢?应为容器的值类型,即Bag::value_type。然而,在这种情况下,Bag只是一个模板参数,编译器无法知道value_type成员实际上是一种类型。但可以使用typename关键字来指出,类成员是typedef:

vector<string>::value_type st; // vector<string> a defined class
typename Bag::value_type m;     // Bag an as yet undefined type

对于上述第一个定义,编译器能够访问vector模板定义,该定义指出,value_type是一个typedef;对于第二个定义,typename关键字指出,无论Bag将会是什么,Bag::value-type都将是类型的名称。这些考虑因素导致了下面的定义:

template<typename Bag>
typename Bag::value_type min(const Bag & b)
{
    typename Bag::const_iterator it;
    typename Bag::value_type m = *b.begin();
    for (it = b.begin(); it != b.end(); ++it)
        if (*it < m)
            m = *it;
    return m;
}

这样,便可以这样使用该模板函数:

vector<int> temperatures;
// input temperature values into the vector
int coldest = min(temperatures);

temperatures参数将使得Bag被谓词为vector,而typename Bag::value-type被谓词为vector ::value_type,进而为int。

所有的容器都还可以包含表G.2列出的成员函数或操作。其中,X是容器类型,如vector;而T是存储在容器中的类型,如int。另外,a和b是类型为X的值;u是标识符;r是类型为X的非const值;rv是类型为X的非const右值,而移动操作是C++11新增的。

表G.2 为所有容器定义的操作

| 操作 | 描述 | | :----- | :----- | :----- | :----- | | X u; | 创建一个名为u的空对象 | | X() | 创建一个空对象 | | X(a) | 创建对象x的拷贝 | | X u(a) | u是a的拷贝(复制构造函数) | | X u = a; | u是a的拷贝(复制构造函数) | | r = a | r等于a的值(复制赋值) | | X u(rv) | u等于rv的原始值(移动构造函数) | | X u = rv | u等于rv的原始值(移动构造函数) | | a = rv | u等于rv的原始值(移动赋值) | | (&a)->~X() | 对a的每个元素执行析构函数 | | begin() | 返回一个指向第一个元素的迭代器 | | end() | 返回一个指向超尾的迭代器 | | cbegin() | 返回一个指向第一个元素的const迭代器 | | cend() | 返回一个指向超尾的const迭代器 | | size() | 返回元素数目 | | maxsize() | 返回容器的最大可能长度 | | empty() | 如果容器为空,则返回true | | swap() | 交换两个容器的内容 | | = = | 如果两个容器的长度相同、包含的元素相同且元素排列的顺序相同,则返回true | | ! = | a!=b返回!(a= =b) |

使用双向或随机迭代器的容器(vector、list、deque、array、set和map)是可反转的,它们提供了表G.3所示的方法。

表G.3 为可反转容器定义的类型和操作

| 操作 | 描述 | | :----- | :----- | :----- | :----- | | X::reverse_iterator | 指向类型T的反向迭代器 | | X::const_reverse_iterator | 指向类型T的const反向迭代器 | | a.rbegin() | 返回一个反向迭代器,指向a的超尾 | | a.rend() | 返回一个指向a的开头的反向迭代器 | | a.crbegin() | 返回一个const反向迭代器,指向a的超尾 | | a.crend() | 返回一个指向a的开头的const反向迭代器 |

无序集合(set)和无序映射(map)无需支持表G.4所示的可选容器操作,但其他容器必须支持。

表G.4 可选的容器操作

| 操作 | 描述 | | :----- | :----- | :----- | :----- | | < | 如果a按词典顺序排在b之前,则a<b返回true | | > | a>b返回b<a | | <= | a<=b返回!(a>b) | | >= | a>=b返回!(a<b) |

容器的>运算符假设已经为值类型定义了>运算符。词典比较是一种广义的按字母顺序排序,它逐元素地比较两个容器,直到两个容器中对应的元素相同时为止。在这种情况下,元素对的顺序将决定容器的顺序。例如,如果两个容器的前10个元素都相同,但第一个容器的第11个元素比第二个容器的第11个元素小,则第一个容器将排在第二个容器之前。如果两个容器中的元素一直相同,直到其中一个容器中的元素用完,则较短的容器将排在较长的容器之前。