2.3 如何运行 选用了目前在Windows平台下较为常见的Microsoft Visual C++ 6.0和Borland C++ Builder 6.0作为例子。 尽管Visual C++ 6.0对最新的ANSI/ISO C++标准支持的并不是很好。不过据称Visual C++ .NET(也就是VC7.0) 在这方面的性能有所改善。 你可以选用多种方式运行前面的程序,比如在Visual C++下,你可以直接在DOS命令行状态下编译运行,也可以在VC的 IDE下采用控制台应用程序(Console Application)的方式运行。对于C++ Builder,情况也类似。 对于Visual C++而言,如果是在DOS命令行状态下,你首先需要找到它的编译器。假定你的Visual C++装在 C:\Program Files\Microsoft Visual Studio\VC98下面,则其编译器所在路径应该是 C:\Program Files\Microsoft Visual Studio\VC98\Bin, 在那里你可以找到cl.exe文件。编译时请加上/GX和/MT参数。如果一切正常,结果就会产生一个可执行文件。如下所示: cl /GX /MT example2_2.cpp 前一个参数用于告知编译器允许异常处理(Exception Handling)。在P. J. Plauger STL中的很多地方使用了 异常处理机制(即try…throw…catch语法),所以应该加上这个参数,否则会有如下警告信息: warning C4530: C++ exception handler used, but unwind semantics are not enabled. 后一个参数则用于使程序支持多线程,它需要在链接时使用LIBCMT.LIB库文件。不过P. J. Plauger STL 并不是线程安全的(thread safety)。如果你是在VC环境下使用像STLport这样的STL实现版本, 则需要加上这个参数,因为STLport是线程安全的。 如果在IDE环境下,可以在新建工程的时候选择控制台应用程序. 
至于那些参数的设置,则可以通过在Project功能菜单项中的Settings功能【Alt+F7】中设置编译选项来完成。

有时,在IDE环境下编译STL程序时,可能会出现如下警告信息(前面那几个示例程序不会出现这种情况): warning C4786: '……' : identifier was truncated to '255' characters in the debug information 这是因为编译器在Debug状态下编译时,把程序中所出现的标识符长度限制在了255个字符范围内。如果超过最大长度,这些标识 符就无法在调试阶段查看和计算了。而在STL程序中大量的用到了模板函数和模板类,编译器在实例化这些内容时,展开之后所产 生的标识符往往很长(没准会有一千多个字符!)。如果你想认识一下这个warning的话,很简单,在程序里加上如下一行代码: vector<string> string_array; // 类似于字符串数组变量 对于这样的warning,当然可以置之不理,不过也是有解决办法的。 你可以在文件开头加入下面这一行: #pragma warning(disable: 4786)。 它强制编译器忽略这个警告信息,这种做法虽然有点粗鲁,但是很有效。 study 的版本是 Release 3.3: June 8, 2000 SGI STL被GCC(linux下的C++编译器)所采用,你可以在GCC的Include子目录下找到所有头文件(比如:C:\cygnus\cygwin -b20\include\g++\include)。 Which compilers are supported? The STL has been tested on these compilers: SGI 7.1 and later, or 7.0 with the -n32 or -64 flag; gcc 2.8 or egcs 1.x; Microsoft 5.0 and later. Introduction to the Standard Template LibraryThe Standard Template Library, or STL, is a C++ library of container classes, algorithms, and iterators; it provides many of the basic algorithms and data structures of computer science. The STL is a generic library, meaning that its components are heavily parameterized: almost every component in the STL is a template. Containers and algorithms Like many class libraries, the STL includes container classes: classes whose purpose is to contain other objects. The STL includes the classes vector, list, deque, set, multiset, map, multimap, hash_set, hash_multiset, hash_map, and hash_multimap. Each of these classes is a template, and can be instantiated to contain any type of object. You can, for example, use a vector<int> in much the same way as you would use an ordinary C array, except that vector eliminates the chore of managing dynamic memory allocation by hand. vector<int> v(3); // Declare a vector of 3 elements.
v[0] = 7;
v[1] = v[0] + 3;
v[2] = v[0] + v[1]; // v[0] == 7, v[1] == 10, v[2] == 17
The STL also includes a large collection of algorithms that manipulate the data stored in containers. You can reverse the order of elements in a vector, for example, by using the reverse algorithm. reverse(v.begin(), v.end()); // v[0] == 17, v[1] == 10, v[2] == 7
The reason for both of these facts is the same: reverse, like other STL algorithms, is decoupled from the STL container classes. This means that reverse can be used not only to reverse elements in vectors, but also to reverse elements in lists, and even elements in C arrays. The following program is also valid. double A[6] = { 1.2, 1.3, 1.4, 1.5, 1.6, 1.7 };
reverse(A, A + 6);
for (int i = 0; i < 6; ++i)
cout << "A[" << i << "] = " << A;
This example uses a range, just like the example of reversing a vector: the asymmetrical notation is a reminder that the two endpoints are different, that the first is the beginning of the range and the second is one past the end of the range. Iteratorswhat exactly does reverse declare its arguments to be, and what exactly do v.begin() and v.end() return? The answer is that the arguments to reverse are iterators, which are a generalization of pointers. Iterators are the mechanism that makes it possible to decouple algorithms from containers: algorithms are templates, and are parameterized by the type of iterator, so they are not restricted to a single type of container. Consider, for example, how to write an algorithm that performs linear search through a range. This is the STL's find algorithm. template <class InputIterator, class T>
InputIterator find(InputIterator first, InputIterator last, const T& value) {
while (first != last && *first != value) ++first;
return first;
} First and last are declared to be of type InputIterator, and InputIterator is a template parameter. That is, there isn't actually any type called InputIterator: when you call find, the compiler substitutes the actual type of the arguments for the formal type parameters InputIterator and T. If the first two arguments to find are of type int* and the third is of type int, then it is as if you had called the following function. int* find(int* first, int* last, const int& value) {
while (first != last && *first != value) ++first;
return first;
}
Concepts and ModelingOne very important question to ask about any template function, not just about STL algorithms, is what the set of types is that may correctly be substituted for the formal template parameters. The basic answer, then, is that find implicitly defines a set of requirements on types, and that it may be instantiated with any type that satisfies those requirements. Concepts are not a part of the C++ language; Nevertheless, concepts are an extremely important part of the STL. Using concepts makes it possible to write programs that cleanly separate interface from implementation: the author of find only has to consider the interface specified by the concept Input Iterator, rather than the implementation of every possible type that conforms to that concept. Similarly, if you want to use find, you need only to ensure that the arguments you pass to it are models of Input Iterator. This is the reason why find and reverse can be used with lists, vectors, C arrays, and many other types: programming in terms of concepts, rather than in terms of specific types, makes it possible to reuse software components and to combine components together. Container A Container is an object that stores other objects (its elements), and that has methods for accessing its elements. In particular, every type that is a model of Container has an associated iterator type that can be used to iterate through the Container's elements. There is no guarantee that the elements of a Container are stored in any definite order; the order might, in fact, be different upon each iteration through the Container. Nor is there a guarantee that more than one iterator into a Container may be active at any one time. (Specific types of Containers, such as Forward Container, do provide such guarantees.) A Container "owns" its elements: the lifetime of an element stored in a container cannot exceed that of the Container itself. Sequence A Sequence is a variable-sized Container whose elements are arranged in a strict linear order. It supports insertion and removal of elements. Associative Container An Associative Container is a variable-sized Container that supports efficient retrieval of elements (values) based on keys. It supports insertion and removal of elements, but differs from a Sequence in that it does not provide a mechanism for inserting an element at a specific position. Iterators Iterators are a generalization of pointers: they are objects that point to other objects. As the name suggests, iterators are often used to iterate over a range of objects: if an iterator points to one element in a range, then it is possible to increment it so that it points to the next element. Iterators are central to generic programming because they are an interface between containers and algorithms: algorithms typically take iterators as arguments, so a container need only provide a way to access its elements using iterators. This makes it possible to write a generic algorithm that operates on many different kinds of containers, even containers as different as a vector and a doubly linked list. The STL defines several different concepts related to iterators, several predefined iterators, and a collection of types and functions for manipulating iterators. Function objects A Function Object, or Functor (the two terms are synonymous) is simply any object that can be called as if it is a function. An ordinary function is a function object, and so is a function pointer; more generally, so is an object of a class that defines operator(). Carpicorn:here is the overview about the STL. The next section is the studying from Container Classes.
|