📄 ei49.htm
字号:
<P><A NAME="dingp20"></A>
but that won't compile. "What is this <CODE>basic_string</CODE> of which you speak?," your compilers will wonder, though they'll probably phrase the question rather differently. No, to declare <CODE>string</CODE>, you would first have to declare all the templates on which it depends. If you could do it, it would look something like <NOBR>this:<SCRIPT>create_link(20);</SCRIPT>
</NOBR></P>
<A NAME="223639"></A>
<UL><PRE>template<class charT> struct char_traits;
</PRE>
</UL><A NAME="223640"></A>
<UL><PRE>template<class T> class allocator;
</PRE>
</UL><A NAME="223641"></A>
<UL><PRE> template<class charT,
class traits = char_traits<charT>,
class Allocator = allocator<charT> >
class basic_string;
</PRE>
</UL><A NAME="223642"></A>
<UL><PRE>typedef basic_string<char> string;
</PRE>
</UL><A NAME="223643"></A>
<A NAME="dingp21"></A>However, you can't declare <CODE>string</CODE>. At least you shouldn't. That's because library implementers are allowed to declare <CODE>string</CODE> (or anything else in the <CODE>std</CODE> namespace) differently from what's specified in <NOBR><FONT COLOR="#FF0000" SIZE="-2"><B>°</B></FONT><A HREF="http://www.awl.com/cseng/cgi-bin/cdquery.pl?name=cstandard" onMouseOver = "self.status = 'The latest publicly-available version of the C++ standard'; return true" onMouseOut = "self.status = self.defaultStatus" TARGET="_top">the</NOBR> standard</A> as long as the result offers standard-conforming behavior. For example, a <CODE>basic_string</CODE> implementation could add a fourth template parameter, but that parameter's default value would have to yield code that acts as the standard says an unadorned <CODE>basic_string</CODE> <NOBR>must.<SCRIPT>create_link(21);</SCRIPT>
</NOBR></P>
<A NAME="223644"></A>
<P><A NAME="dingp22"></A>
End result? Don't try to manually declare <CODE>string</CODE> (or any other part of the standard library). Instead, just include the appropriate header, e.g. <CODE><string></CODE>.<SCRIPT>create_link(22);</SCRIPT>
</P>
<A NAME="223646"></A>
<P><A NAME="dingp23"></A>
With this background on headers and templates under our belts, we're in a position to survey the primary components of the standard C++ <NOBR>library:<SCRIPT>create_link(23);</SCRIPT>
</NOBR></P><UL><A NAME="223648"></A>
<A NAME="dingp24"></A><LI><B>The standard C library.</B> It's still there, and you can still use it. A few minor things have been tweaked here and there, but for all intents and purposes, it's the same C library that's been around for years.<SCRIPT>create_link(24);</SCRIPT>
<A NAME="223651"></A>
<P><A NAME="dingp25"></A><LI><B>Iostreams.</B> Compared to "traditional" iostream implementations, it's been templatized, its inheritance hierarchy has been modified, it's been augmented with the ability to throw exceptions, and it's been updated to support strings (via the <CODE>stringstream</CODE> classes) and internationalization (via locales — see below). Still, most everything you've come to expect from the iostream library continues to exist. In particular, it still supports stream buffers, formatters, manipulators, and files, plus the objects <CODE>cin</CODE>, <CODE>cout</CODE>, <CODE>cerr</CODE>, and <CODE><A NAME="p229"></A>clog</CODE>. That means you can treat <CODE>string</CODE>s and files as streams, and you have extensive control over stream behavior, including buffering and formatting.<SCRIPT>create_link(25);</SCRIPT>
</P>
<A NAME="223665"></A>
<A NAME="28081"></A>
<P>
<A NAME="dingp26"></A><LI><B>Strings.</B> <CODE>string</CODE> objects were designed to eliminate the need to use <CODE>char*</CODE> pointers in most applications. They support the operations you'd expect (e.g., concatenation, constant-time access to individual characters via <CODE>operator[]</CODE>, etc.), they're convertible to <CODE>char*</CODE>s for compatibility with legacy code, and they handle memory management automatically. Some <CODE>string</CODE> implementations employ reference counting (see <A HREF="../MEC/MI29_FR.HTM#6073" TARGET="_top">Item M29</A>), which can lead to <I>better</I> performance (in both time and space) than <CODE>char*</CODE>-based strings.<SCRIPT>create_link(26);</SCRIPT>
<A NAME="183443"></A>
<P>
<A NAME="dingp27"></A><LI><B>Containers.</B> Stop writing your own basic container classes! The library offers efficient implementations of vectors (they act like dynamically extensible arrays), lists (doubly-linked), queues, stacks, deques, maps, sets, and bitsets. Alas, there are no hash tables in the library (though many vendors offer them as extensions), but compensating somewhat is the fact that <CODE>string</CODE>s are containers. That's important, because it means anything you can do to a container (see below), you can also do to a <CODE>string</CODE>.<SCRIPT>create_link(27);</SCRIPT>
<A NAME="195382"></A>
<P>
What's that? You want to know how I <I>know</I> the library implementations are efficient? Easy: the library specifies each class's interface, and part of each interface specification is a set of performance guarantees. So, for example, no matter how <CODE>vector</CODE> is implemented, it's not enough to offer just <I>access</I> to its elements, it must offer <I>constant-time</I> access. If it doesn't, it's not a valid <CODE>vector</CODE> <NOBR>implementation.<SCRIPT>create_link(28);</SCRIPT>
</NOBR></P>
<A NAME="195384"></A>
<P><A NAME="dingp29"></A>
In many C++ programs, dynamically allocated strings and arrays account for most uses of <CODE>new</CODE> and <CODE>delete</CODE>, and <CODE>new</CODE>/<CODE>delete</CODE> errors — especially leaks caused by failure to delete <CODE>new</CODE>ed memory — are distressingly common. If you use <CODE>string</CODE> and <CODE>vector</CODE> objects (both of which perform their own memory management) instead of <CODE>char*</CODE>s and pointers to dynamically allocated arrays, many of your <CODE>new</CODE>s and <CODE>delete</CODE>s will vanish, and so will the difficulties that frequently accompany their use (e.g., Items <A HREF="./EI6_FR.HTM#1885" TARGET="_top">6</A> and <A HREF="./EI11_FR.HTM#2042" TARGET="_top">11</A>).<SCRIPT>create_link(29);</SCRIPT>
</P>
<A NAME="27223"></A>
<A NAME="dingp30"></A><LI><B>Algorithms.</B> Having standard containers is nice, but it's even nicer when there's an easy way to do things with them. The standard library offers over two dozen easy ways (i.e., predefined functions, officially known as <I>algorithms</I> — they're really function templates), most of which work with <I>all</I> the containers in the library — as well as with built-in arrays!<SCRIPT>create_link(30);</SCRIPT>
<A NAME="27863"></A>
<P><A NAME="dingp31"></A>
<A NAME="p230"></A>Algorithms treat the contents of a container as a sequence, and each algorithm may be applied to either the sequence corresponding to all the values in a container or to a subsequence. Among the standard algorithms are <CODE>for_each</CODE> (apply a function to each element of a sequence), <CODE>find</CODE> (find the first location in a sequence holding a given value — <A HREF="../MEC/MI35_FR.HTM#5473" TARGET="_top">Item M35</A> shows its implementation), <CODE>count_if</CODE> (count the number of elements in a sequence for which a given predicate is true), <CODE>equal</CODE> (determine whether two sequences hold equal-valued elements), <CODE>search</CODE> (find the first position in one sequence where a second sequence occurs as a subsequence), <CODE>copy</CODE> (copy one sequence into another), <CODE>unique</CODE> (remove duplicate values from a sequence), <CODE>rotate</CODE> (rotate the values in a sequence) and <CODE>sort</CODE> (sort the values in a sequence). Note that this is just a <I>sampling</I> of the algorithms available; the library contains many <NOBR>others.<SCRIPT>create_link(31);</SCRIPT>
</NOBR></P>
<A NAME="27824"></A>
<P><A NAME="dingp32"></A>
Just as container operations come with performance guarantees, so do algorithms. For example, the <CODE>stable_sort</CODE> algorithm is required to perform no more than O(N log N) comparisons. (If the "Big O" notation in the previous sentence is foreign to you, don't sweat it. What it really means is that, broadly speaking, <CODE>stable_sort</CODE> must offer performance at the same level as the most efficient general-purpose serial sorting <NOBR>algorithms.)<SCRIPT>create_link(32);</SCRIPT>
</NOBR></P>
<A NAME="27840"></A>
<A NAME="dingp33"></A><LI><B>Support for internationalization.</B> Different cultures do things in different ways. Like the C library, the C++ library offers features to facilitate the production of internationalized software, but the C++ approach, though conceptually akin to that of C, is different. It should not surprise you, for example, to learn that C++'s support for internationalization makes extensive use of templates, and it takes advantage of inheritance and virtual functions, too.<SCRIPT>create_link(33);</SCRIPT>
<A NAME="27747"></A>
<P><A NAME="dingp34"></A>
The primary library components supporting internationalization are <I>facets</I> and <I>locales</I>. Facets describe how particular characteristics of a culture should be handled, including collation rules (i.e., how strings in the local character set should be sorted), how dates and times should be expressed, how numeric and monetary values should be presented, how to map from message identifiers to (natural) language-specific messages, etc. Locales bundle together sets of facets. For example, a locale for the United States would include facets describing how to sort strings in American English, read and write dates and times, read and write monetary and numeric values, etc., in a way appropriate for people in the USA. A locale for France, on the other hand, would describe how to perform these tasks in a manner to which the French are accus<A NAME="p231"></A>tomed. C++ allows multiple locales to be active within a single program, so different parts of an application may employ different conventions.<SCRIPT>create_link(34);</SCRIPT>
<A NAME="27682"></A>
<P><A NAME="dingp35"></A>
<A NAME="dingp35"></A><LI><B>Support for numeric processing.</B> The end for FORTRAN may finally be near. The C++ library offers a template for complex number classes (the precision of the real and imaginary parts may be <CODE>float</CODE>, <CODE>double</CODE>, or <CODE>long</CODE> <CODE>double</CODE>) as well as for special array types specifically designed to facilitate numeric programming. Objects of type <CODE>valarray</CODE>, for example, are defined to hold elements that are free from aliasing. This allows compilers to be much more aggressive in their optimizations, especially for vector machines. The library also offers support for two different types of array slices, as well as providing algorithms to compute inner products, partial sums, adjacent differences, and more.<SCRIPT>create_link(35);</SCRIPT>
<A NAME="27228"></A>
<P>
<A NAME="dingp36"></A><LI><B>Diagnostic support.</B> The standard library offers support for three ways to report errors: via C's assertions (see <A HREF="./EI7_FR.HTM#1894" TARGET="_top">Item 7</A>), via error numbers, and via exceptions. To help provide some structure to exception types, the library defines the following hierarchy of exception <NOBR>classes:<SCRIPT>create_link(36);</SCRIPT>
</NOBR></P>
<SPAN ID="Image1of1" STYLE="position: absolute; z-index:1; visibility: hidden"><IMG SRC="./IMAGES/GRAPHICS/DIAGRAMS/I_231A1.GIF" BORDER=0></SPAN>
<SPAN ID="Image1of2" STYLE="position: absolute; z-index:1; visibility: hidden"><IMG SRC="./IMAGES/GRAPHICS/DIAGRAMS/I_231A2.GIF" BORDER=0></SPAN>
<SPAN ID="Image1of3" STYLE="position: absolute; z-index:1; visibility: hidden"><IMG SRC="./IMAGES/GRAPHICS/DIAGRAMS/I_231A3.GIF" BORDER=0></SPAN>
<SPAN ID="Image1of4" STYLE="position: absolute; z-index:1; visibility: hidden"><IMG SRC="./IMAGES/GRAPHICS/DIAGRAMS/I_231A4.GIF" BORDER=0></SPAN>
<SPAN ID="Image1of5" STYLE="position: absolute; z-index:1; visibility: hidden"><IMG SRC="./IMAGES/GRAPHICS/DIAGRAMS/I_231A5.GIF" BORDER=0></SPAN>
<SPAN ID="Image1of6" STYLE="position: relative; z-index:1; visibility: hidden"><IMG SRC="./IMAGES/GRAPHICS/DIAGRAMS/I_231A5.GIF" BORDER=0></SPAN>
<P><A NAME="dingp37"></A><A NAME="27562"></A>
Exceptions of type <CODE>logic_error</CODE> (or its subclasses) represent errors in the logic of software. In theory, such errors could have been prevented by more careful programming. Exceptions of type <CODE>runtime_error</CODE> (or its derived classes) represent errors detectable only at <NOBR>runtime.<SCRIPT>create_link(37);</SCRIPT>
</NOBR></P>
<A NAME="28142"></A>
<P><A NAME="dingp38"></A>
You may use these classes as is, you may inherit from them to create your own exception classes, or you may ignore them. Their use is not <NOBR>mandatory.<SCRIPT>create_link(38);</SCRIPT>
</NOBR></P>
</UL>
<A NAME="27231"></A>
<P><A NAME="dingp39"></A>
<A NAME="p232"></A>This list doesn't describe everything in the standard library. Remember, the specification runs over 300 pages. Still, it should give you the basic lay of the <NOBR>land.<SCRIPT>create_link(39);</SCRIPT>
</NOBR></P>
<A NAME="27886"></A>
<P><A NAME="dingp40"></A>
The part of the library pertaining to containers and algorithms is commonly known as <I>Standard Template Library</I> (the STL — see <A HREF="../MEC/MI35_FR.HTM#5473" TARGET="_top">Item M35</A>). There is actually a third component to the STL — Iterators — that I haven't described. Iterators are pointer-like objects that allow STL algorithms and containers to work together. You need not understand iterators for the high-level description of the standard library I give here. If you're interested in them, however, you can find examples of their use in Items <A HREF="./EI39_FR.HTM#7269" TARGET="_top">39</A> and <A HREF="../MEC/MI35_FR.HTM#5473" TARGET="_top">M35</A>.<SCRIPT>create_link(40);</SCRIPT>
</P>
<A NAME="27945"></A>
<P><A NAME="dingp41"></A>
The STL is the most revolutionary part of the standard library, not because of the containers and algorithms it offers (though they are undeniably useful), but because of its architecture. Simply put, the architecture is extensible: you can <I>add</I> to the STL. Of course, the components of the standard library itself are fixed, but if you follow the conventions on which the STL is built, you can write your own containers, algorithms, and iterators that work as well with the standard STL components as the STL components work with one another. You can also take advantage of STL-compliant containers, algorithms, and iterators written by others, just as they can take advantage of yours. What makes the STL revolutionary is that it's not really software, it's a set of <I>conventions</I>. The STL components in the standard library are simply manifestations of the good that can come from following those <NOBR>conventions.<SCRIPT>create_link(41);</SCRIPT>
</NOBR></P>
<A NAME="27988"></A>
<P><A NAME="dingp42"></A>
By using the components in the standard library, you can generally dispense with designing your own from-the-ground-up mechanisms for stream I/O, strings, containers (including iteration and common manipulations), internationalization, numeric data structures, and diagnostics. That leaves you a lot more time and energy for the really important part of software development: implementing the things that distinguish your wares from those of your <NOBR>competitors.<SCRIPT>create_link(42);</SCRIPT>
</NOBR></P>
<DIV ALIGN="CENTER"><FONT SIZE="-1">Back to <A HREF="EI48_FR.HTM" TARGET="_top">Item 48: Pay attention to compiler warnings.</A> <BR> Continue to <A HREF="EI50_FR.HTM" TARGET="_top">Item 50: Improve your understanding of C++.</A></DIV></FONT>
</BODY>
</HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -