05-大部分容器都有的成员
G.2 大部分容器都有的成员
所有容器都定义了表G.1列出的类型。在这个表中,x为容器类型,如vector
| 类型 | 值 | | :----- | :----- | :----- | :----- | | 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
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
所有的容器都还可以包含表G.2列出的成员函数或操作。其中,X是容器类型,如vector
| 操作 | 描述 | | :----- | :----- | :----- | :----- | | 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所示的方法。
| 操作 | 描述 | | :----- | :----- | :----- | :----- | | 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所示的可选容器操作,但其他容器必须支持。
| 操作 | 描述 | | :----- | :----- | :----- | :----- | | < | 如果a按词典顺序排在b之前,则a<b返回true | | > | a>b返回b<a | | <= | a<=b返回!(a>b) | | >= | a>=b返回!(a<b) |
容器的>运算符假设已经为值类型定义了>运算符。词典比较是一种广义的按字母顺序排序,它逐元素地比较两个容器,直到两个容器中对应的元素相同时为止。在这种情况下,元素对的顺序将决定容器的顺序。例如,如果两个容器的前10个元素都相同,但第一个容器的第11个元素比第二个容器的第11个元素小,则第一个容器将排在第二个容器之前。如果两个容器中的元素一直相同,直到其中一个容器中的元素用完,则较短的容器将排在较长的容器之前。