34-函数和容器方法
16.6.4 函数和容器方法
有时可以选择使用STL方法或STL函数。通常方法是更好的选择。首先,它更适合于特定的容器;其次,作为成员函数,它可以使用模板类的内存管理工具,从而在需要时调整容器的长度。
例如,假设有一个由数字组成的链表,并要删除链表中某个特定值(例如4)的所有实例。如果la是一个list
la.remove(4); // remove all 4s from the list
调用该方法后,链表中所有值为4的元素都将被删除,同时链表的长度将被自动调整。
还有一个名为remove()的STL算法(见附录G),它不是由对象调用,而是接受区间参数。因此,如果lb是一个list
remove(lb.begin(), lb.end(), 4);
然而,由于该remove()函数不是成员,因此不能调整链表的长度。它将没被删除的元素放在链表的开始位置,并返回一个指向新的超尾值的迭代器。这样,便可以用该迭代器来修改容器的长度。例如,可以使用链表的erase()方法来删除一个区间,该区间描述了链表中不再需要的部分。程序清单16.18演示了这是如何进行的。
程序清单16.18 listrmv.cpp
// listrmv.cpp -- applying the STL to a string
#include <iostream>
#include <list>
#include <algorithm>
void Show(int);
const int LIM = 10;
int main()
{
using namespace std;
int ar[LIM] = {4, 5, 4, 2, 2, 3, 4, 8, 1, 4};
list<int> la(ar, ar + LIM);
list<int> lb(la);
cout << "Original list contents:\n\t";
for_each(la.begin(), la.end(), Show);
cout << endl;
la.remove(4);
cout << "After using the remove() method:\n";
cout << "la:\t";
for_each(la.begin(), la.end(), Show);
cout << endl;
list<int>::iterator last;
last = remove(lb.begin(), lb.end(), 4);
cout << "After using the remove() function:\n";
cout << "lb:\t";
for_each(lb.begin(), lb.end(), Show);
cout << endl;
lb.erase(last, lb.end());
cout << "After using the erase() method:\n";
cout << "lb:\t";
for_each(lb.begin(), lb.end(), Show);
cout << endl;
return 0;
}
void Show(int v)
{
std::cout << v << ' ';
}
下面是程序清单16.18中程序的输出:
Original list contents:
4 5 4 2 2 3 4 8 1 4
After using the remove() method:
la: 5 2 2 3 8 1
After using the remove() function:
lb: 5 2 2 3 8 1 4 8 1 4
After using the erase() method:
lb: 5 2 2 3 8 1
从中可知,remove()方法将链表la从10个元素减少到6个元素。但对链表lb应用remove()后,它仍然包含10个元素。最后4个元素可任意处理,因为其中每个元素要么为4,要么与已经移到链表开头的值相同。
尽管方法通常更适合,但非方法函数更通用。正如您看到的,可以将它们用于数组、string对象、STL容器,还可以用它们来处理混合的容器类型,例如,将矢量容器中的数据存储到链表或集合中。