STL
的目的是标准化组件,这样就不用重新开发,可以使用现成的组件。
STL
现在是
C++
的一部分,因此不用额外安装什麽。它被内建在编译器之内。现在
,来看一看
STL
的
list
。
定义一个
list
可以象这样来定义一个
STL
的
list
:
#include
<
string
>
#include
<
list
>
int main (void) {
list
<
string
>
Milkshakes;
return 0;}
list
<
string
>
Milkshakes
声明了
list
<
string
>模板类
的一个实例,然后就是实例化该类的一个对象。
使用
list
的成员函数
push_back
和
push_front
插入一个元素到
list
中:
#include
<
string
>
#include
<
list
>
int main (void) {
list
<
string
>
Milkshakes;
Milkshakes.push_back("Chocolate");
Milkshakes.push_back("Strawberry");
Milkshakes.push_front("Lime");
Milkshakes.push_front("Vanilla");
return 0;}
现在有个
4
个字符串在
list
中。
list
的成员函数
push_back()
把一个对象放到一个
list
的后面,而
push_front()
把对象放到前面。通常把一些错误信息
push_back()
到一个
list
中去,然后
push_front()
一个标题到
list
中,
这样它就会在这个错误消息以前打印它了。
list
的成员函数
empty()
知道一个
list
是否为空很重要。如果
list
为空,
empty()
这个成员函数返回真。
通常会这样使用它。通篇程序都用
push_back()
来把错误消息放到
list
中去。然后,通过调用
empty()
就可以知道这个程序是否报告了错误。如果定义了一个
list
来放信息,一个放警告,一个放严重错误,
就可以通过使用
empty()
轻易的说出到底有那种类型的错误发生了。
// Using a list to track and report program messages and status #include
<
iostream.h
>
#include
<
string
>
#include
<
list
>
int main (void) {
#define OK 0
#define INFO 1
#define WARNING 2
int return_code;
list
<
string
>
InfoMessages;
list
<
string
>
WarningMessages;
// during a program these messages are loaded at various points
InfoMessages.push_back("Info: Program started");
// do work...
WarningMessages.push_back("Warning: No Customer records have been found");
// do work...
return_code = OK;
if (!InfoMessages.empty()) {
// there were info messages
InfoMessages.push_front("Informational Messages:");
// ... print the info messages list, we'll see how later
return_code = INFO;
}
if (!WarningMessages.empty()) {
// there were warning messages
WarningMessages.push_front("Warning Messages:");
// ... print the warning messages list, we'll see how later
return_code = WARNING;
}
// If there were no messages say so.
if (InfoMessages.empty() && WarningMessages.empty()) {
cout
<<
"There were no messages "
<<
endl;
}
return return_code;}
用
for
循环来处理
list
中的元素
想要遍历一个
list
,比如打印一个中的所有对象来看看
list
上不同操作的结果。要一个元素一个元素的遍历一个
list
,
可以这样做:
/*|| How to print the contents of a simple STL list. Whew! */#include
<
iostream.h
>
#include
<
string
>
#include
<
list
>
int main (void) {
list
<
string
>
Milkshakes;
list
<
string
>
::iterator MilkshakeIterator;
Milkshakes.push_back("Chocolate");
Milkshakes.push_back("Strawberry");
Milkshakes.push_front("Lime");
Milkshakes.push_front("Vanilla");
// print the milkshakes
Milkshakes.push_front("The Milkshake Menu");
Milkshakes.push_back("*** Thats the end ***");
for (MilkshakeIterator=Milkshakes.begin(); MilkshakeIterator!=Milkshakes.end(); ++MilkshakeIterator)
{
// dereference the iterator to get the element
cout
<<
*MilkshakeIterator
<<
endl;
} }
这个程序定义了一个
iterator MilkshakeIterator
。把它指向了这个
list
的第一个元素。
这可以调用
Milkshakes.begin()
来作到,它会返回一个指向
list
开头的
iterator
。然后把它和
Milkshakes.end()
的
返回值来做比较。
容器的
end()
函数会返回一个指向容器的最后一个位置的
iterator
。
list
容器不支持在
iterator
加一个数来指向隔一个的对象。
就是说,不能用
Milkshakes.begin()+2
来指向
list
中的第三个对象,因为
STL
的
list
是以双链的
list
来实现的,
它不支持随机存取。
vector
和
deque(
向量和双端队列
)
和一些其他的
STL
的容器可以支持随机存取。
用
STL
的通用算法
for_each
来处理
list
中的元素
使用
STL list
和
iterator
,我们要初始化、比较和给
iterator
增量来遍历这个容器。
STL
通用的
for_each
算法能够减轻我们的工作。
/*|| How to print a simple STL list MkII*/#include
<
iostream.h
>
#include
<
string
>
#include
<
list
>
#include
<
algorithm
>
PrintIt (string& StringToPrint) {
cout
<<
StringToPrint
<<
endl;}int main (void) {
list
<
string
>
FruitAndVegetables;
FruitAndVegetables.push_back("carrot");
FruitAndVegetables.push_back("pumpkin");
FruitAndVegetables.push_back("potato");
FruitAndVegetables.push_front("apple");
FruitAndVegetables.push_front("pineapple");
for_each (FruitAndVegetables.begin(), FruitAndVegetables.end(), PrintIt);}
使用
STL
的通用算法
for_each()
来遍历一个
iterator
的范围,然后调用
PrintIt()
来处理每个对象。
我们不需要初始化、比较和给
iterator
增量。
for_each()
为我们的完成了这些工作。
for_each
算法引用了
iterator
范围的概念,这是一个由起始
iterator
和一个末尾
iterator
指出的范围。
起始
iterator
指出操作由哪里开始,末尾
iterator
指明到哪结束,但是它不包括在这个范围内。
用
STL
的通用算法
count()
来统计
list
中的元素个数
STL
的通用算法
count()
和
count_it()
用来给容器中的对象记数。就象
for_each()
一样,
count()
和
count_if()
算法也是在
iterator
范围内来做的。
在一个学生测验成绩的
list
中来数一数满分的个数。这是一个整型的
List
。
// How to count objects in an STL list#include
<
list
>
#include
<
algorithm
>
#int main (void) {
list
<
int
>
Scores;
#
Scores.push_back(100); Scores.push_back(80);
Scores.push_back(45); Scores.push_back(75);
Scores.push_back(99); Scores.push_back(100);
#
int NumberOf100Scores(0);
count (Scores.begin(), Scores.end(), 100, NumberOf100Scores);
#
cout
<<
"There were "
<<
NumberOf100Scores
<<
" scores of 100"
<<
endl;}
count()
算法统计等于某个值的对象的个数。上面的例子它检查
list
中的每个整型对象是不是
100
。每次容器中的对象等于
100
,它就给
NumberOf100Scores
加
1
。
用
STL
的通用算法
count_if()
来统计
list
中的元素个数
count_if()
是
count()
的一个更有趣的版本,采用了
STL
的一个新组件,函数对象。
count_if()
带一个函数对象的参数。函数对象是一个至少带有一个
operator()
方法的类。有些
STL
算法作为参数接收
函数对象并调用这个函数对象的
operator()
方法。
函数对象被约定为
STL
算法调用
operator
时返回
true
或
false
。它们根据这个来判定这个函数。
count_if()
通过传递一个函数对象来作出比
count()
更加复杂的评估以确定一个对象是否应该被记数。举个例子:
/*|| Using a function object to help count things*/#include
<
string
>
#include
<
list
>
#include
<
algorithm
>
const string ToothbrushCode("0003");class IsAToothbrush {
public:
bool operator() ( string& SalesRecord )
{
return SalesRecord.substr(0,4)==ToothbrushCode;
} };int main (void) {
list
<
string
>
SalesRecords;
SalesRecords.push_back("0001 Soap");
SalesRecords.push_back("0002 Shampoo");
SalesRecords.push_back("0003 Toothbrush");
SalesRecords.push_back("0004 Toothpaste");
SalesRecords.push_back("0003 Toothbrush");
int NumberOfToothbrushes(0);
count_if (SalesRecords.begin(), SalesRecords.end(),
IsAToothbrush(), NumberOfToothbrushes);
cout
<<
"There were "
<<
NumberOfToothbrushes
<<
" toothbrushes sold"
<<
endl;}
这个程序是这样工作的:定义一个函数对象类
IsAToothbrush
,这个类的对象能判断出卖出的是否是牙刷
。如果这个记录是卖出牙刷的记录的话,函数调用
operator()
返回一个
true
,否则返回
false
。
count_if()
算法由第一和第二两个
iterator
参数指出的范围来处理容器对象。它将对每个
IsAToothbrush()
返回
true
的容器中的对象增加
NumberOfToothbrushes
的值。最后的结果是
NumberOfToothbrushes
这个变量保存了产品代码域为
"0003"
的记录的个数,也就是牙刷的个数。
注意
count_if()
的第三个参数
IsAToothbrush()
,它是由它的构造函数临时构造的一个对象。你可以把
IsAToothbrush
类的一个临时对象
传递给
count_if()
函数。
count_if()
将对该容器的每个对象调用这个函数。
使用
count_if()
的一个更加复杂的函数对象
进一步的研究一下函数对象。假设我们需要传递更多的信息给一个函数对象。我们不能通过
调用
operator
来作到这点,因为必须定义为一个
list
的中的对象的类型。
然而我们通过为
IsAToothbrush
指出一个非缺省的构造函数就可以用任何我们所需要的信息来初始化它了。
例如,我们可能需要每个牙刷有一个不定的代码。我们可以把这个信息加到下面的函数对象中:
/*|| Using a more complex function object*/#include
<
iostream.h
>
#include
<
string
>
#include
<
list
>
#include
<
algorithm
>
class IsAToothbrush {
public:
IsAToothbrush(string& InToothbrushCode) :
ToothbrushCode(InToothbrushCode) {}
bool operator() (string& SalesRecord)
{
return SalesRecord.substr(0,4)==ToothbrushCode;
}
private:
string ToothbrushCode; };int main (void) {
list
<
string
>
SalesRecords;
SalesRecords.push_back("0001 Soap");
SalesRecords.push_back("0002 Shampoo");
SalesRecords.push_back("0003 Toothbrush");
SalesRecords.push_back("0004 Toothpaste");
SalesRecords.push_back("0003 Toothbrush");
string VariableToothbrushCode("0003");
int NumberOfToothbrushes(0);
count_if (SalesRecords.begin(), SalesRecords.end(),
IsAToothbrush(VariableToothbrushCode),
NumberOfToothbrushes);
cout
<<
"There were "
<<
NumberOfToothbrushes
<<
" toothbrushes matching code "
<<
VariableToothbrushCode
<<
" sold"
<<
endl;}
这个例子演示了如何向函数对象传递信息。可以定义任意想要的构造函数,可以在函数对象中做任何想做的处理,都可以合法编译通过。
可以看到函数对象扩展了基本记数算法。
转载请注明原文地址: https://ibbs.8miu.com/read-29015.html