您的位置:首页 > 编程语言 > C语言/C++

读书摘要:C++ Standard Library, The: A Tutorial and Reference

2008-03-17 21:15 495 查看
C++ Standard Library, The: A Tutorial and Reference[/b]

Chap 2 Introduction to C++ and the Standard Library[/b]

2.1    history[/b]

   string classes are designed as a safe and convenient component. Thus,
they provide an almost self-explanatory interface and check for many
errors in the interface.

   The STL was designed to combine
different data structures with different algorithms while achieving the
best performance. Thus, the STL is not very convenient and it is not
required to check for many logical errors. To benefit from the powerful
framework and great performance of the STL, you must know the concepts
and apply them carefully.

   A template is not compiled once to
generate code usable for any type; instead, it is compiled for each
type or combination of types for which it is used. This leads to an
important problem in the handling of templates in practice: You must
have the implementation of a template function available when you call
it, so that you can compile the function for your specific type.
Therefore, the only portable way of using templates at the moment is to
implement them in header files by using inline functions.

2.2    New Language Features[/b]

2.2.1    Templates[/b]

    Non-type Template Parameters[/b]

   
In addition to type parameters, it is also possible to use nontype
parameters. A nontype parameter is then considered as part of the type.

    Default Template Parameters[/b]

    Templates classes may have default arguments

    Keyword Typename[/b]

   
Note that typename is always necessary to qualify an identifier of a
template as being a type, even if an interpretation that is not a type
would make no sense. Thus, the general rule in C++ is that any
identifier of a template is considered to be a value, except it is
qualified by typename.

    Member Templates[/b]

   
Member functions of classes may be templates. However, member templates
may not be virtual, nor may they have default parameters.

    This feature is often used to support automatic type conversions for members in template classes. By providing a different template type for the member function, you relax the rule of exact match.

    A special form of a member template is a template constructor. Template constructors are usually provided to enable implicit type conversions
when objects are copied. Note that a template constructor does not hide
the implicit copy constructor. If the type matches exactly, the
implicit copy constructor is generated and called.

    Nested Template Classes

[/b]
2.2.2    Explicit Initialization for Fundamental Types[/b]

    If you use the syntax of an explicit constructor call without arguments, fundamental types are initialized with zero

2.2.3    Exception Handling[/b]

2.2.4    Namespace[/b]

   
Unlike classes, namespaces are open for definitions and extensions in
different modules. Thus you can use namespaces to define modules,
libraries, or components even by using multiple files.

    A namespace defines logical modules instead of physical modules.

    using directives in header files is really bad design.

2.2.5    Type bool[/b]

2.2.6    Keyword explicit[/b]

    Note that explicit also rules out the initialization with type conversion by using the assignment syntax:

                   
   Stack s1(40);        // OK
   Stack s2 = 40;       // ERROR[/b]

    This is because there is a minor difference between
                   
    X x;
    Y y(x);       // explicit conversion

    and
                   
    X x;
    Y y = x;      // implicit conversion

   
The former creates a new object of type Y by using an explicit
conversion from type X, whereas the latter creates a new object of type
Y by using an implicit conversion.

2.2.8    Initialization of Constant Static Members[/b]

   
It is now possible to initialize integral constant static members
inside the class structure. This is useful when the constant is used in
the class structure after the initialization. For example:

                   
   class MyClass {
       static const int num = 100;
       int elems[num];
       ...
   };

    Note that you still have to to define space for a constant static member that is initialized within a class definition:
           
    const int MyClass::num;     // no initialization here

Chap 3 General Concept

[/b]
3.3    Error and Exception Handling[/b]

    These standard exception classes can be divided into three groups:

   1.    Exceptions for language support:

    bad_alloc[/b]            (new)
    bad_cast [/b]            (dynamic_cast)
    bad_typeid[/b]          (typeid)
    bad_exception[/b]   (unexpected())

   2.    Exceptions for the C++ standard library:usually derived from class logic_error

    invalid_argument
    length_error
    out_of_range
    domain_error
    ios_base::failure[/b]

   3.    Exceptions for errors outside the scope of a program:derived from runtime_error

    range_error[/b]
    overflow_error[/b]
    underflow_error[/b]

3.4    Allocators[/b]

   
An allocator represents a special memory model. It is used as
abstraction to translate the need to use memory into a raw call for
memory.

    It serves as a base for technical solutions that use certain memory models, such as shared memory, garbage collection, and object-oriented databases, without changing the interfaces.

    default allocator:[/b] Only occasionally does it make sense to program  customized allocators.

Chapter 4 Utilities[/b]

4.1    class pair[/b]

   the container classes map and multimap use pairs to manage their elements

   make_pair()[/b]

   makes it convenient to pass two values of a pair directly to a function that requires a pair as its argument

4.2    auto_ptr[/b]

   
Note that class auto_ptr<> does not allow you to initialize an
object with an ordinary pointer by using the assignment syntax. Thus,
you must initialize the auto_ptr directly by using its value :

   std::auto_ptr<ClassA> ptr1(new ClassA);     //OK
   std::auto_ptr<ClassA> ptr2 = new ClassA;    //[/b]ERROR[/b]

    The transfer of ownership implies a special use for auto_ptrs----that is, functions can use them to transfer ownership to other functions.

   
constant auto_ptrs reduce the danger of an unintended transfer of
ownership.The const does not mean that you can't change the value of
the object the auto_ptr owns (if any). You can't change the ownership
of a constant auto_ptr; however, you can change the value of the object
to which it refers.

    auto_ptrs are not provided for arrays!

    auto_ptrs don't meet the requirements for container elements.Fortunately, the design of the language and library prevents this misuse from compiling in a standard-conforming environment.

   
we  needs to find a mechanism to enable an rvalue to be converted to an
lvalue.Thus, the auto_ptr_ref class was introduced to provide this
convert-to-lvalue mechanism.

4.3    numeric_limits<>[/b]

    numeric_limits is a typical example of specialization of a general template

    The specializations are provided for any fundamental type that can represent numeric values

4.4    Auxiliary Functions:min, max, swap[/b]

    min() and max() require that both types match.

    comparison criterion as an additional argument.

   
The big advantage of using swap()is that it enables to provide special
implementations for more complex types by using template specialization
or function overloading.These special implementations might save time
by swapping internal members rather than by assigning the objects. This
is the case, for example, for all standard containers and strings .

4.5    Supplementary Comparison Operators[/b]

    Four template functions define the comparison operators !=, >, <=, and >= by calling the operators == and <.
   
    they are defined in a subnamespace of std, i.e, std::rel_ops.

4.6    Header Files <cstddef> and <cstdlib>[/b]

    In C++,NULL is simply value 0.Note that in C, NULL often is defined as (void*)0. This is incorrect in C++ because there the type of NULL must be an integer type. Otherwise, you
could not assign NULL to a pointer. This is because in C++ there is no
automatic conversion from void* to any other pointer type.

Chapter 5 STL[/b]

    The STL's flexibility, however, has a price, chief of which is that it is not self-explanatory.

5.1    STL Components[/b]

    The concept of the STL is based on a separation of data and operations.The
data is managed by container classes, and the operations are defined by
configurable algorithms. Iterators are the glue between these two
components. They let any algorithm interact with any container.

5.1    Components

[/b]    In
a way, the STL concept contradicts the original idea of object-oriented
programming: The STL separates data and algorithms rather than
combining them.

5.2    Containers[/b]

    Sequence containers[/b]: element's position depends on the time and place of the insertion, but it is independent of the value of the element.

    Associative containers[/b]:actual position of an element depends on its value due to a certain sorting criterion.

    The key advantage of automatic sorting is better performance when you search elements. In particular, you can always use a binary search[/b], which results in logarithmic complexity rather than linear complexity.

    Strictly speaking, the particular implementation of any container is not defined inside the C++ standard library. However, the behavior and complexity specified by the standard do not leave much room for variation. So, in practice, the implementations differ only in minor details.

   
Usually, the STL containers provide only those special member functions
that in general have "good" timing.This prevents a programmer from
calling a function that might cause bad performance.

    Note that list.pop_front() does not return the element it removed.

    By default, associative containers compare the elements or the keys with operator <. However, you can supply your own comparison function to define another ordering criterion.

    Associative containers are typically implemented as Red-Black trees.

    All of these associative container classes have an optional template argument for the sorting criterion.
The default sorting criterion is the operator <. The sorting
criterion is also used as the test for equality; that is, two elements
are equal if neither is less than the other.

    Container Adapters[/b]: Stack,Queue,Priority Queue.

5.3    Iterators[/b]

    fundamental operations of an iterator:

    Operator  *
    Operator  ++ and --
    Operator  == and !=
    Operator  =

   
In fact, each container class defines its iterator type as a nested
class.As a result, iterators share the same interface but have
different types.Because the iterator is defined by the container, it
surely does the right thing.

    begin() and end() define a half-open range.It has 2 advantage:

    1.You have a simple end criterion for loops that iterate over the elements: They simply continue as long as end() is not reached.

    2. It avoids special handling for empty ranges. For empty ranges, begin() is equal to end().

    Every container defines two iterator types:
   
        container::  iterator
        container::  const_iterator

    You can't use the subscript operator([]) for multimaps.

    Random access iterator provide operators for iterator arithmetic(in
accordance with "pointer arithmetic" of an ordinary pointer).The
iterators of the container classes vector and deque, and iterators of
strings are random access iterators.

5.4    Algorithms

[/b]   
Algorithms are not member functions of the container classes. Instead,
they are global functions that operate with iterators.Instead of each
algorithm being implemented for each container type, all are
implemented only once for any container type.

    Note that this is not an object-oriented programming paradigm; it is a generic functional programming paradigm.

    Ensuring the ranges are valid is not always as easy as it sounds.If this is not the case, the behavior is undefined

    Every algorithm processes half-open ranges.

    Multiple Ranges:Several
algorithms process more than one range. In this case you usually must
define both the beginning and the end only for the first range. For all
other ranges you need to pass only their beginnings.

5.5    Iterator Adapters[/b]

    Iterators are pure abstractions: Anything that behaves like an iterator is an iterator.

5.5.1    Insert Iterators[/b]

    Insert iterators, or inserters,are used to let algorithms operate in
insert mode rather than in overwrite mode.In particular, they solve the
problem of algorithms that write to a destination that does not have
enough room: they let the destination grow accordingly.

    As for Inserter Iterator,A call to step forward is a "no-op"

    Three predefined insert iterators:[/b]

    Back inserters:insert the elements at the back of their container (appends them) by calling push_back()

    Front inserters: insert the elements at the front of their container by calling push_front()

    General inserters:inserts
elements directly in front of the position that is passed as the second
argument of its initialization. It calls the insert() member function
with the new value and the new position as arguments.For associative containers, the position is taken as a hint
to start the search for the correct position. If the position is not
correct, however, the timing may be worse than if there was no hint

5.5.2    Stream Iterators[/b]

    Stream iterators are iterators that read from and write to a stream.

5.5.3    Reverse Iterators[/b]

   
The advantage of using reverse iterators is that all algorithms are
able to operate in the opposite direction without special code.

5.6    Manipulating Algorithms[/b]

5.6.1    "Removing" Elements[/b]

    The price of the flexibility of the STL:[/b]

    In general, iterators do not
know their containers(knowing its type ,though). Thus, the algorithms,
which use the iterators to access the elements of the container, can't
call any member function of the container.

5.6.2    Manipulating Algorithms and Associative Containers[/b]

    Manipulation algorithms can't  use associative containers as a destination;it will results in a failure at compile time

5.6.3    Algorithms versus Member Functions[/b]

   
Even if you are able to use an algorithm, it might be a bad idea to do
so. A container might have member functions that provide much better
performance.

5.8    Functions as Algorithm Arguments[/b]

5.8.2    Predicates[/b]

   
Predicates are functions that return a Boolean value.The STL requires
that predicates always yield the same result for the same parameters.

5.9 Function Objects[/b]

    There are rarely things that are not possible in C++!
[/b]
   
It is true that functors do complicate code. However, function objects
are more than functions, and they have some advantages:

    1.    Function objects are "smart functions."
    2.    Each function object has its own type
    3.    Function objects are usually faster than ordinary functions.

5.9.2    Predefined Function Objects[/b]

   
A typical example is a function object used as a sorting criterion.

    What is interesting is that all these function objects are usually declared inline. Thus, you use a function-like notation or abstraction, but you get good performance.

5.10    Container Elements[/b]

    Elements of containers must meet certain requirements because containers handle them in a special way.

5.10.1    Requirements for Container Elements[/b]

    1.An element must be copyable by a copy constructor. The generated copy should be equivalent to the source.

    2.An element must be assignable by the assignment operator.

    3.An element must be destroyable by a destructor

    4.For some member functions of sequence containers, the default constructor must be available.

    5.For several operations, the test of equality with operator == must be defined.

    6.For associative containers[/b]
the operations of the sorting criterion must be provided by the
elements. By default, this is the operator <, which is called by the
less<> function object.

5.10.2    Value Semantics or Reference Semantics[/b]

    The approach of the STL, only to support value semantics, has strengths and weaknesses

5.11    Errors and Exceptions Inside the STL[/b]

5.11.1    Error Handling[/b]

   
The design goal of the STL was the best performance rather than the
most security.Error checking wastes time, so almost none is done.

    The C++ standard library states that any use of the STL that violates preconditions results in undefined behavior

5.11.2    Exception Handling[/b]

    The STL almost never checks for logical errors.
Therefore, almost no exceptions are generated by the STL itself due to
a logical problem.In fact, there is only one function call for which
the standard requires that it might cause an exception directly: the
at() member function for vectors and deques.

    The C++
standard library  provides the following basic guarantee for exception
safety: will not leak resources or violate container invariants in the
face of exceptions.

    For all node-based containers (lists,
sets, multisets, maps and multimaps), any failure to construct a node
simply leaves the container as it was.

    All array-based containers (vectors and deques) do not fully recover when an element gets inserted.

Chapter 6. STL Containers

[/b]

6.1    Common Container Abilities and Operations[/b]

    Container's constructors are member templates

    Assignments VS swap():swap() offers much better efficiency

6.2    Vectors[/b]

6.2.1    Abilities of Vectors[/b]

    vector's iterators are random access iterators, so you can use any algorithm of the STL

    The capacity of a vector is important for two reasons:

    1.    Reallocation invalidates all references, pointers, and iterators for elements of the vector.

    2.    Reallocation takes time.

    std::vector<int> v;       // create an empty vector
    v.reserve (80);           // reserve memory for 80 elements

    std::vector<T> v(5);      // creates a vector and initializes it with five values
                              // (calls five times the default constructor of type T)

   
It is not possible to call reserve() for vectors to shrink the
capacity.Calling reserve() with an argument that is less than the
current capacity is a no-op.

    Only at() performs range checking   

6.2.3    Using Vectors as Ordinary Arrays[/b]

    You can expect that for any valid index i in vector v, the following yields true:
                   
    &v[i] == &v[0] + i

    It simply means that you can use a vector in all cases in which you could use a dynamic array.

    For Boolean elements of a vector, the C++ standard library provides a specialization of vector:vector<bool>.

    [/b]Better not use vector<bool>!

6.3    Deques[/b]

    It manages its elements with a dynamic array, provides random access, and has almost the same interface as a vector.

   
To provide this ability, the deque is implemented typically as a bunch
of individual blocks, with the first block growing in one direction and
the last block growing in the opposite direction.

6.4    Lists[/b]

    Lists provide many special member functions for moving elements.
These member functions are faster versions of general algorithms that
have the same names. They are faster because they only redirect
pointers rather than copy and move the values.

    List only provide  bidirectional iterators.

    For sorting the elements, lists provide the special member function sort().

6.5    Sets and Multisets[/b]

   
If a special sorting criterion is not passed, the default criterion
less<> is used.The function object less sorts the elements by comparing
them with operator <.

    The sorting criterion must define "strict weak ordering[/b]." Strict weak ordering is defined by the following three properties:
   
    1.    It has to be antisymmetric[/b].(非对称)
    2.    It has to be transitive[/b].(传递性)
    3.    It has to be irreflexive[/b].(非自反)

   
Like all standardized associative container classes, sets and multisets
are usually implemented as balanced binary trees . The
standard does not specify this, but it follows from the complexity of
set and multiset operations.In fact, sets and multisets are typically
implemented as "red-black trees."

    Automatic sorting imposes an important constraint on sets and multisets: You may not change the value of an element directly because this might compromise the correct order.

    The interface reflects this behavior:

    * Sets and multisets don't provide operations for direct element access.

    * Indirect access via iterators has the constraint that, from the iterator's point of view, the element value is constant.

    You can define the sorting criterion in two ways:

    1.As a template paramete[/b]r[/b]

        std::set<int,std::greater<int> > coll;

        This is the usual way to specify the sorting criterion.In this case, the sorting criterion is part of the type.

    2.As a constructor parameter

        In this case, you might have a type with several sorting criteria.

    Sets and multisets are optimized for fast searching of elements, so they provide special search functions.

    Assignments[/b]

   
For these operations both containers must have the same type. In
particular, the type of the comparison criteria must be the same,
although the comparison criteria themselves may be different.

    Inserting and removing[/b]

     * Sets provide the following interface:
                           
         pair<iterator,bool> insert(const value_type& elem);
         iterator            insert(iterator pos_hint,const value_type& elem);
       
    * Multisets provide the following interface:
                                     
         iterator            insert(const value_type& elem);
         iterator            insert(iterator pos_hint, const value_type& elem);

                                 
6.6    Maps and Multimaps[/b]

    The elements of a map or multimap may have any types Key and T that meet the following two requirements:

           1.    The key/value pair must be assignable and copyable.

           2.    The key must be comparable with the sorting criterion.

    In fact, sets, multisets, maps, and multimaps typically use the same internal data type.

    maps can be used as associative arrays.

    To check whether a map container is less than another map container is done by a lexicographical comparison.

   
More important is the constraint that the key of all elements inside a
map and a multimap is considered to be constant.So,you can't call any
modifying algorithm if the destination is a map or multimap.

6.6.3    Using Maps as Associative Arrays[/b]

   
Associative containers don't typically provide abilities for direct
element access. Instead, you must use iterators. For maps, however,
there is an exception to this rule.

    This behavior of an associative array has both advantages and disadvantages:

    The advantage is that you can insert new elements into a map with a more convenient interface.

    The disadvantage is that you might insert new elements by accident or mistake.

    multimap is the typical container for dictionaries.

6.7    Other STL Containers[/b]

    There are three different approaches to making containers "STL-able"

         invasive approach:         provide the interface that ah STL container requires

         noninvasive approach:    provide special iterators

         wrapper approach:         combining the two previous approaches

    The string classes of the C++ standard library are an example of the invasive approach of writing STL containers

    string can be considered containers of characters.

6.8    Implementing Reference Semantics[/b]

   
STL container classes provide value semantics but not
reference semantics.if you want reference semantics in STL
containers,you should use a smart pointer class that avoids possible
errors.

Chapter 7. STL Iterators[/b]

7.2    Iterator Categories[/b]

    sorting algorithms require iterators that can perform random access because otherwise the runtime would be poor

   
Two input iterators are equal if they occupy the same position.
However, as stated previously, this does not mean that they return the
same value on element access.

    Output iterators are the counterparts of input iterators.You can't check whether an output iterator is valid or whether a "writing" was successful.

    [/b]Note: input iterators are comparable while ouptut iterator are not

    Another typical example of output iterators are inserters. Inserters are iterators that insert values into containers

    Forward iterators[/b]
are combinations of input and output iterators.Unlike input iterators
and output iterators, forward iterators can refer to the same element
in the same collection and process the same element more than once.

    Bidirectional iterators[/b] are forward iterators that provide the additional ability to iterate backward over the elements.

    Random access iterators[/b]
are bidirectional iterators that are bidirectional iterators that
support  "iterator arithmetic". That is ,hey can add and subtract
offsets, process differences, and compare iterators with relational
operators such as < and >

7.2.6    The Increment and Decrement Problem of Vector Iterators[/b]

    In general, you can increment and decrement temporary iterators. However, for vectors and strings, you typically can't.[/b]

    The reason for this strange problem lies in the fact that vector iterators are typically implemented as ordinary pointers.[/b]

7.3    Auxiliary Iterator Functions[/b]

    Three auxiliary functions for iterators: advance()[/b], [/b]distance()[/b], [/b]and iter_swap()[/b]

    void advance (InputIterator& pos, Dist n)

    Note that advance() does not check
whether it crosses the end() of a sequence (it can't check because
iterators in general do not know the containers on which they operate).
Thus, calling this function might result in undefined behavior because
calling operator ++ for the end of a sequence is not defined.

    Dist distance (InputIterator pos1, InputIterator pos2)

    Dist's type :  iterator_traits<InputIterator>::difference_type

    The first iterator must refer to an element that is not after the element of the second iterator. Otherwise, the behavior is undefined.

    distance() has bad performance for other than random access iterators.

    void iter_swap (ForwardIterator1 pos1, ForwardIterator2 pos2)

    The iterators don't need to have the same type. However, the values must be assignable.

7.4    Iterator Adapters[/b]

7.4.1    Reverse Iterators[/b]

    Reverse iterators are adapters that redefine increment and decrement operators so that they behave in reverse

   
You can convert normal iterators to reverse iterators. Naturally, the
iterators must be bidirectional iterators, but note that the logical position of an iterator is moved during the conversion .This is not a bug; it's a feature!

    logical position (the value returned )[/b] VS  physical position (the element pointed to )[/b]

    Within a conversion from an iterator to a reverse iterator,physical position stays the same.[/b]

    You can convert reverse iterators back to normal iterators using the base() member function provided by reverse iterators.

   
Again, physical position (the element the iterator pointer to) is retained, but
the logical position (the value the iterator returns ) is changed.

7.4.2    Insert Iterators[/b]

    The C++ standard library provides three kinds of insert iterators: back inserters, front inserters, and general inserters.Each uses a different member function, which it calls for the container to which it belongs

7.4.3    Stream Iterators[/b]

   
The implementation of an ostream iterator uses the same concept as the
implementation of insert iterators .The only difference is that they transform the assignment of a new value into an output operation by using operator >>.

   
Istream iterators are the counterparts of ostream iterators.However,
istream iterators are a bit more complicated than ostream iterators (as
usual, reading is more complicated than writing).

    end-of-stream iterator[/b]:created with the default constructor for istream iterators.If a read fails, every istream iterator becomes an end-of-stream iterator.

7.5    Iterator Traits[/b]

    For each iterator category, the C++ standard library provides an iterator tag that can be used as a "label" for iterators

    C++ standard library provides a special template structure to define the iterator traits.

    template <class T> struct iterator_traits {...}

Chapter 8. STL Function Objects[/b]

8.1    The Concept of Function Objects[/b]

    3 important advantages of functors:

    1.    A function object might be smarter because it may have a state.
    2.    Each function object has its own type.
    3.    A function object is usually faster than a function pointer.

    There are 2 ways to get a "result" or "feedback" from using function objects with algorithms:

    1.    You can pass the function objects by reference.To pass a function
object by reference you simply have to explicitly qualify the call of
the algorithm so that the function object type is a reference

    2.    You can use the return value of the for_each() algorithm.for_each() has the unique ability to return its function object (no other algorithm can do this)

8.1.4    Predicates versus Function Objects[/b]

    Not every function that returns a Boolean value is a valid predicate for the STL.

    A predicate must be "pure function".

8.2    Predefined Function Objects[/b]

    less<> is the default criterion
whenever objects are sorted or compared, so it is used often. Default
sorting operations always produce an ascending order (element  < 
nextElement).

8.2.1    Function Adapters[/b]

    bind1st,bind2rd,not1,not2

   
A function adapter is a function object that enables the combining of
function objects with each other, with certain values, or with special
functions.

    Function adapters are function objects themselves.

   
By using function adapters you can combine different function objects
to form very powerful expressions. This kind of programming is called functional composition[/b].

8.2.2    Function Adapters for Member Functions[/b]

    mem_fun_ref,mem_fun

   
The adapter is necessary because you can't pass a member function
directly to an algorithm. Doing so would cause a compile-time error

   
mem_fun adapters are for sequences that contain pointers to elements.
Probably mem_fun_ptr would have been a less confusing name .

    Both mem_fun_ref and mem_fun can call member functions with zero or one argument. However, you can't call member functions with two or more arguments in this way.

    Note that the member functions called by mem_fun_ref and mem_fun must be constant member functions. Unfortunately, the C++ standard library does not provide function adapters for nonconstant member functions

8.2.3    Function Adapters for Ordinary Functions[/b]
   
    ptr_fun

8.2.4    User-Defined Function Objects for Function Adapters[/b]

   
You can write your own function objects, but to use them in combination
with function adapters they must meet certain requirements: They must
provide type members for the type of their arguments and the result.
The C++ standard library provides structures to make this more
convenient:

    unary_function,binary_function

8.3    Supplementary Composing Function Objects[/b]

    In general it should be possible to define almost every functional behavior as a combination of function objects. However, the C++ standard library does not provide enough adapters to support this.

[/b]

Chapter 9. STL Algorithms[/b]

9.2    Algorithm Overview[/b]

    Algorithms work in overwrite mode rather than in insert mode.
Thus, the caller must ensure that destination ranges have enough
elements. You can use special insert iterators (see Section 7.4.2) to
switch from overwrite to insert mode.

    To increase their
flexibility and power, several algorithms allow the user to pass
user-defined operations, which they call internally. These operations
might be ordinary functions or function objects. If these functions
return a Boolean value , they are called predicates

    The _if suffix[/b]

        Generally, if there is a version of an algorithm which takes a predicate, it gets the name of the algorithm with the     suffix _if.

    The _copy suffix[/b]

        The _copy suffix is used as an indication that elements are not only manipulated but also copied into a         destination range

    Non-modifying Algorithms[/b]

        One of the most important algorithms is for_each()

    Modifying Algorithms[/b]

        The fundamental modifying algorithms are for_each() and transform()

        Nevertheless, to be safe you should call merge() only for sorted ranges.

        You can't use associative containers as a destination for modifying algorithms.

    Removing Algorithms[/b]

        As with modifying algorithms, you can't use an associative container as a destination

   
    Note that removing algorithms remove elements logically only by
overwriting them with the following elements     that were not removed.
Thus, they do not change the number of elements in the ranges on which
they operate.     Instead, they return the position of the new "end" of the
range

    Mutating Algorithms[/b]

   
    Mutating algorithms are algorithms that change the order of elements
(and not their values) by assigning and     swapping their values.As with
modifying algorithms, you can't use an associative container as a
destination

    Sorting Algorithms[/b]

   
    Sorting algorithms are a special kind of mutating algorithm.However,
sorting is more complicated and therefore     usually takes more time than
simple mutating operations

        As with modifying algorithms, you can't use an associative container as a destination

   
    In fact, these algorithms usually have worse than linear complexity 
and require random access iterators (for the     destination).

        sort() is based historically on quicksort

        partial_sort() is based historically on heapsort

        stable_sort() is also based historically on heapsort

        The standard guarantees complexity, but not how it is implemented

    Sorted Range Algorithms[/b]

   
    Sorted range algorithms require that the ranges on which they
operate are sorted according to their sorting     criterion.

9.4    The for_each() Algorithm[/b]

9.5    Nonmodifying Algorithms

[/b]
Chapter 10. Special Containers[/b]

    Container Adapters:Stack,Queue,Priority queue

10.1    Stack

[/b]    Stack's low-level default container is deque;however,You can use any
sequence container class that provides the member functions back(), push_back(), and pop_back().

    The core interface of stack:

    push()
    pop()
    top()
[/b]
    The standard class stack<> prefers speed over convenience and safety

10.2    Queue[/b]
   
    queue 's low-level default  container is  also deque;  however You can use any sequence container class that provides the member functions front(), back(),[/b] push_back(), and pop_front().

    The core interface of queues:

    push()[/b]
    front()[/b]
    back()[/b]
    pop()[/b]
    [/b]
10.3    Priority Queues
   
[/b]    The class priority_queue<> implements a queue from which elements are read according to their priority.

   
As usual ,you can provide the sorting criterion as a template
parameter. By default, the elements are sorted by using operator <
in descending order.

    Unlike queue, priority_queue use vector as its default low-level container; however,You can use any sequence container class that provides random access iterators and the member functions front(), push_back(), and pop_back().

    Random access is necessary for sorting the elements, which is performed by the heap algorithms of the STL

    The core interface of priority queues:

    push()[/b]
    top()[/b]
    pop([/b])

    queue's member function push() and pop() will call STL algorithm push_heap() internally.
   
    Note that, unlike other container adapters, no comparison operators are defined.

10.4    Bitsets

[/b]    Bitsets model fixed-sized arrays of bits or Boolean values.

    You can't change the number of bits in a bitset. The number of bits is the template parameter.

    The class bitset is defined as a template class with the number of bits as the template parameter

   
For bitsets, some special constructors are defined. However, there is
no special copy constructor, assignment operator, and destructor defined

    some useful member functions  provided by  bitset

    bitset<bits>::bitset( ) :       Creates a bitset with all bits initialized with zero.

   
bitset<bits>::bitset(unsigned long value)   Creates a bitset
that is initialized according to the bits of the integral value value.

   
explicit bitset<bits>::bitset (const string& str)   Create a
bitset that is initialized by the string str  which may contain only
the characters '0' and '1'.

    size_t bitset<bits>::size() const   Returns the number of bits

    size_t bitset<bits>::count() const   Returns the number of set bits

    bool bitset<bits>::any() const   Returns whether any bit is set.

    bool bitset<bits>::none() const   Returns whether no bit is set.

    bitset<bits>& bitset<bits>::set(size_t idx)   Sets the bit at position idx to true.

    bitset<bits>& bitset<bits>::reset()   Resets all bits to false

    bitset<bits>& bitset<bits>::flip()   Toggles all bits (sets unset bits and vice versa)
   
   
Operator [ ] returns a special temporary object of type
bitset<>::reference when it is called for non-constant bitsets.

    unsigned long bitset<bits>::to_ulong( ) const   Returns the integral value that the bits of the bitset represent

   
string bitset<bits>::to_string () const   Returns a string that
contains the value of the bitset as a binary representation written
with characters '0' for unset bits and '1' for set bits

   

   

Chapter 11. Strings[/b]

11.1    Motivation [/b]

    Modern data processing is mostly string processing

    find()[/b]

    All these find functions return an index of the first matching position.Yes,the return value is an integer and not an iterator.

    The return type of all find functions is string::size_type.

[/b]    Unlike C-strings, objects of class string have no special character '/0' at the end of the string.

    If the search fails, a special value is needed to return the failure. That value is npos, which is also defined by the string class.

    The type and value of npos are a big pitfall
for the use of strings.

    Be very careful that you always use
string::size_type and not int or unsigned for the return type when you
want to check the return value of a find function
   
    At all places where an index and a length are used as arguments, strings behave according to the following two rules:

    1.    index must have a valid value;otherwise it throws out_of _range.
    2.    number of characters could have any value;In particular, string::npos always works as a synonym for "all remaining characters."

    Both size() and length() return the numberof characters. In particular,
size() has nothing to do with the memory that the string
uses.(length()这个名字体现了典型的C函数strlen的风格,size()这个名字则体现了典型STL成员函数的风格)

   The function getline() is a special function to read input from streams
into a string. It reads every character up to the next end-of-line,
which by default is the newline character.

    string::size_type is an unsigned integral type

11.2    Description of the String Classes
[/b]
    In most cases ,character '/0' is not treated as a special character that terminate the string

    In general, a string might contain any character. In particular, a string might contain the contents of a binary file

    Operations that Are Not Provided
   
[/b]        1.    Regular expressions
        2.    Word processing (capitalization, case-insensitive comparisons)

11.2.3    Constructors and Destructors[/b]

   
You can't initialize a string with a single character.This means that
there is an automatic type conversion from type const char* but not
from type char to type string.

11.2.4    Strings and C-Strings[/b]

    You can use ordinary C-strings in almost every situation where strings are combined with other string-like objects

    However, there is no automatic type conversion from a string object to a C-string. This is for safety reasons.

   
Note that string do not provide a special meaning for the character
'/0', which is used as special character in an ordinary C-string to
mark the end of the string. The character '/0' may be part of a string
just like every other character.

    There are three possible ways to convert the contents of the string into a raw array of characters or C-string:

    1.data( )

    Returns the contents of the string as an array of characters. Note that the return type is not a valid C-string because no '/0' character gets appended

    2.c_str( )

    Returns the contents of the string as a C-string. Thus, the '/0' character is appended
   
    3.copy( )

    Copies the contents of the string into a character array provided by the caller. An '/0' character is not appended.

   
Note that data() and c_str() return an array that is owned by the
string. Thus, the caller must not modify or free the memory. The return
value of c_str() and data() is valid only until the next call of a
non-constant member function for the same string

11.2.5    Size and Capacity[/b]

    For strings, three "sizes" exist:

    1.    size() and length()

    Return the actual number of characters of the string. Both functions are equivalent

    2.    max_size()

   
Returns the maximum number of characters that a string may contain.this
value usually is the maximum value of the type of the index less one.

    3.    [/b]capacity()[/b]

    Returns the number of characters that a string could contain without having to reallocate its internal memory

    Member function reserve()
is provided to avoid reallocations.Unlike vectors, you can call
reserve() for strings to shrink the capacity.If the argument is less
than the current number of characters, it is a nonbinding shrink-to-fit
request.The default value of reserve() for string is 0. So, a call of
reserve() without any argument is always a nonbinding shrink-to-fit
request

    The standard, however, specifies that capacity may shrink only because of a call of reserve().

11.2.7    Comparisons
[/b]
   
If strings are compared by <, <=, >, or >=, their
characters are compared lexicographically according to the current
character traits.

11.2.8    Modifiers

[/b]    The specialization of swap() for strings guarantees constant complexity.

11.2.11    Searching and Finding

[/b]    All search functions have the word find inside their name.

    If the search fails, they return npos

11.2.12    The Value npos

[/b]   
Be very careful when using the string value npos and its type. When you
want to check the return value always use string::size_type and not int
or unsigned for the type of the return value; otherwise, the comparison
of the return value with string::npos might not work.

    This behavior is the result of the design decision that npos is defined as -1

    static const size_type npos = -1;

   
Unfortunately, size_type (which is defined by the allocator of the
string) must be an unsigned integral type.Because -1 is converted
into an unsigned integral type, npos is the maximum unsigned value of
its type

    To write portable code, however, you should always use string::size_type for any index of your string type

11.2.13    Iterator Support for Strings[/b]

    String iterators are random access iterators. This means that tyou can use all algorithms

    To support the use of back inserters[/b] for string, the push_back() function is defined

11.2.14    Internationalization

[/b]   
The character traits are provided to specify the details of how to deal
with aspects depending on the representation of a character type

11.2.15    Performance[/b]

   
The standard does not specify how the string class is to be
implemented. It only specifies the interface. There may be important
differences in speed and memory usage depending on the concept and
priorities of the implementation.

    If you prefer better speed, make sure that your string class uses a concept such as reference counting

11.2.16    Strings and Vectors

[/b]    Primary difference between string and vector is their goal:

    The primary goal of vectors is to handle and to manipulate the elements of the container, not the container as a whole.Thus, vectors implementations are optimized to operate on elements inside the container

   
The primary goal of strings is to handle and to manipulate the
container (the string) as a whole.Thus, strings are optimized to reduce
the costs of assigning and passing the whole container

Chapter 13. Input/Output Using Stream Classes[/b]

    IOStream
library were made templates during standardization.As a side effect,
this renders simple forward declarations of stream classes illegal. A
header was introduced to provide the appropriate declarations: <iosfwd>

13.1    Common Background of I/O Streams

[/b]   
class istream and ostream are instantiations of class template
basic_istream<> and basic_ostream<>, with char as the
template parameter.

13.1.3    Global Stream Objects

[/b]    cin (of class istream)

    cout (of class ostream)

    cerr (of class ostream)  :No buffer
   
    clog (of class ostream):[/b]By default, this stream is connected to the same destination as cerr, with the difference that output to clog is buffered.

13.1.5    Manipulators

[/b]    Manipulators are special objects that are used to manipulate a stream.

    endl          Outputs '/n' and flushes the output buffer
    ends         Outputs '/0'
    flush         Flushes the output buffer
    ws            Reads and discards whitespaces

13.2    Fundamental Stream Classes and Objects

13.2.1    Classes and Class Hierarchy

[/b]    The class templates basic_istream<> and basic_ostream<> derive virtually[/b] from basic_ios<>,

    class template basic_streambuf<> is the heart of the IOStream library.

    The IOStream library is designed with a rigid separation of responsibilities(严格分工).
    
    The classes derived from basic_ios "only" handle formatting of the
data. Actually, they don't even do the formatting! The actual
formatting is delegated to corresponding facets [/b]in the locale library.

   
The actual reading and writing of characters is performed by the stream
buffers maintained by the basic_ios sub-objects.

    In addition, an
abstraction from the external representation (for example files or
strings or socket) is formed by the stream buffers. By using
stream buffers it is quite easy to define access to a new "external
representation" like a new storage device ——derive and custoimize.

    Detailed Class Definitions[/b]

   Here are two instantiations of the class basic_ios<> for the two character types used most often:

    namespace std {
    typedef basic_ios<char> ios;
    typedef basic_ios<wchar_t> wios;
    }

     the class templates basic_istream<>,
basic_ostream<>, and basic_iostream<> are also
parameterized with the character type and a traits class.

13.2.3    Header Files

[/b]    <iosfwd>

    Contains forward declarations
for the stream classes. This header file is necessary because it is no
longer permissible to use a simple forward declaration such as "class
ostream;"

    <istream>

    Contains the definitions for the classes that support input only[/b] (basic_istream<>) and for the classes that support both input and output[/b] (basic_iostream<>).

    <iostream>

    Contains declarations of the global stream objects.

    In general, only those headers defining necessary stuff should be included. In particular, header files should only include <iosfwd>, and the corresponding implementation files [/b]should then include the header with the complete definition.

13.3    Standard Stream Operators << and >>

    Type bool

[/b]   
By default, Boolean values are printed and read numerically: false is
converted from and to 0, and true is converted from and to 1.

    Types char and wchar_t[/b]

    When a char or wchar_t is being read with operator >>, leading whitespace is skipped by default.

    Type char*

[/b]   
A C-string (that is, a char*) is read word-wise. That is, when a
C-string is being read, leading whitespace is skipped by default and
the string is read until another whitespace character or end-of-file is
encountered

    Type void*

[/b]    Operators << and >> also provide the possibility of printing a pointer and reading it back in  again.

13.4    State of Streams[/b]

    For the general state of streams, several constants of type iostate are defined to be used as flags .The type iostate is a member of the class ios_base

    goodbit   eofbit   failbit    badbit
   
   
The exact type of the constants is an implementation detail .it is not
defined whether iostate is an enumeration, a type definition for an
integral type, or an instantiation of the class bitset

    eofbit[/b] normally happens with failbit[/b] because the end-of-file condition is checked and detected when an attempt is made to read beyond end-of-file. After
reading the last character, the flag eofbit is not yet set. The next
attempt to read a character sets eofbit and failbit, because the read
fails.

    These constants are not defined globally. Instead, they are defined within the class

13.4.2    Member Functions Accessing the State of Streams[/b]

    The current state of the flags can be determined by the member functions

    Note that you always have
to clear error bits explicitly.If failbit is set, each following stream
operation is a no-op until failbit is cleared explicitly.

13.4.3    Stream State and Boolean Conditions[/b]

    operator void*()
    operator !()

13.4.4    Stream State and Exceptions[/b]

    To stay backward compatible, by default, streams throw no
exceptions. However, for the standardized streams, it is possible to
define, for every state flag, whether setting that flag will trigger an
exception. This definition is done by the exceptions() member function
   
    The exceptions thrown are objects of the class std::ios_base::failure,which is derived from class exception

13.5 Standard Input/Output Functions[/b]

    The member functions in this section read or write "unformatted" data.

    These functions use type streamsize to specify counts, which is defined in <ios>:

13.5.1    Member Functions for Input[/b]

    When C-strings are read it is safer to use the functions from this section than to use operator >>.

    It is often better to use the stream buffer directly instead of using istream member functions

13.5.2    Member Functions for Output[/b]

    Like the input functions, it may also be reasonable to use the stream buffer directly or to use the template class ostreambuf_iterator for unformatted writing.

13.6    Manipulators[/b]

   
13.6.1 How Manipulators Work[/b]

    Manipulators are nothing more than functions that are passed to the I/O operators as arguments. The functions are then called by the operator.


ostream& ostream::operator << ( ostream& (*op) (ostream&))




...{


// call the function passed as parameter with this stream as the argument


return (*op) (*this);


}

    The manipulator endl() for ostream is implemented basically like this

[/b]


std::ostream& std::endl (std::ostream& strm)




...{


// write newline


strm.put(' ');


// flush the output buffer


strm.flush();


// return strm to allow chaining


return strm;


}

13.7 Formatting

[/b]    Two concepts influence the definition of I/O formats: format flag and locale

[/b]13.7.1    Format Flags
[/b]
    You can also use manipulators to set and clear format flags

    The manipulators setiosflags() and resetiosflags() provide the
possibility of setting or clearing, respectively, one or more flags in
a write or read statement with operator << or >>
respectively

13.7.3    Field Width, Fill Character, and Adjustment[/b]

    Two member functions are used to define the field width and the fill character: width() and fill()

    For the output ,width() defines a minimum field. This definition applies only to the next formatted field written

    fill() defines
the fill character that is used to fill the difference between the
formatted representation of a value and the minimum field width. The
default fill character is a space.

13.7.4    Positive Sign and Uppercase Letters[/b]

    Two format flags are defined to influence the general appearance of numeric values: showpos and uppercase

13.7.7    General Formatting Definitions[/b]

    ios::skipws is set by default, meaning that by default leading whitespaces are skipped by certain read operations.

    ios::unitbuf
controls the buffering of the output. With ios::unitbuf set, output is
basically unbuffered.By default, this flag is not set. However, for the
streams cerr and wcerr this flag is set initially.

13.8    Internationalization[/b]

    Each stream uses an associated locale object. The initial default
locale object is a copy of the global locale object at the construction
time of the stream

    imbue (loc)            Sets the locale object
    getloc()                 Returns the current locale object
    widen (c)               Converts the char character c to a character of the stream's character set
   
narrow (c,def)         Converts character c from the stream's character
set to a char (if there is no such char, def is
                                returned)

13.9    File Access

[/b]   
For streams that are both read and written , it is not possible to
switch arbitrarily between reading and writing .This is a restriction
inherited from C.

13.9.1    File Flags[/b]

    A set of flags is defined in the class ios_base .These flags are of type openmode.

[/b]    ios_base::in    ios_base::out   ios_base::binary   ios_base::append    ios_base::trunc ios_base::ate
    [/b]

    ios_base::binary configures the stream to suppress conversion of
special characters or character sequences such as end-of-line or
end-of-file

    Whether a file is opened for reading and/or for writing is independent [/b]of the corresponding stream object's class. The class only determines the default open mode if no second argument is used.

    The open mode is passed to the corresponding stream buffer class,
which opens the file. However, the operations possible for the object
are determined by the stream's class

    The member function open() does not clear the stream's state flags
   
13.9.2    Random Access[/b]

    Not all stream classes support positioning. For example, positioning the streams cin, cout, and cerr is not defined

    The position's value is type pos_type .The C++ standard library defines a global template class fpos<> [/b]for file positions. Class fpos<> is used to define types streampos for char and wstreampos for wchar_t streams

13.9.3    Using File Descriptors[/b]

    The C++ standard library unfortunately does not provide this
possibility of attaching a stream to an I/O channel using file
descriptors. This is because the language is supposed to be independent
of any operating system.  

13.10    Connecting Input and Output Streams[/b]

13.10.1    Loose Coupling Using tie()[/b]

    You can tie a stream to an output stream. This means the buffers of both streams are synchronized in a way that the buffer of the output stream is flushed before each input or output of the other stream.

    For each stream, you can only have one output stream that is tied
to this stream.However, you can tie an output stream to different
streams.

    By default, the standard input is connected to
the standard output using this mechanism. This ensures that a message
asking for input is flushed before requesting the input.


// predefined connections:


std::cin.tie (&std::cout);


std::wcin.tie (&std::wcout);

    You can also tie one output stream to another output stream

13.10.2    Tight Coupling Using Stream Buffers[/b]

    Using the function rdbuf(), you can couple streams tightly by using a common stream buffer

    Note that the destructor of the classes basic_istream<> and
basic_ostream<> does not delete the corresponding stream buffer
(it was not opened by these classes anyway).

    The advantage
of this approach is that the format does not need to be restored to its
original state after it is modified because the format applies to the stream object, not to the stream buffer.

    Also note that the destruction of a stream object does not flush
the buffer. To make sure that an output buffer is flushed, it has to be
flushed manually

    The fact that stream buffer is not destroyed applies only to basic_istream<> and basic_ostream<>.
The other stream classes destroy the stream buffers they allocated
originally, but they do not destroy stream buffers set with rdbuf()

13.10.3    Redirecting Standard Streams[/b]

    A stream can be redirected by setting a  new stream buffer.

    Stream's member function copyfmt() can be used to assign all format information of a given stream to another stream object

    File streams allocate their stream buffer objects at construction time and destroy them on destruction.

13.10.4    Streams for Reading and Writing

13.11    Stream Classes for Strings

[/b]     String streams provide a buffer but don't have an I/O channel

    Stream classes have a similar relationship to the stream base classes, as do the file stream classes.
   
    The major function in the interface of the string stream classes is the member function str(). This function is used to manipulate the buffer of the string stream classes.

    A typical programming error when dealing with string streams is to
forget to extract the string with the function str(), and instead to
write to the file stream directly.

13.11.2 char* Stream Classes[/b]

    The char* stream classes are retained only for backward
compatibility.Their interface is error prone and they are rarely used
correctly.

13.12    Input/Output Operators for User-Defined Types[/b]

13.12.4    User-Defined Operators Using Unformatted Functions[/b]

    The I/O operators defined in the C++ standard library are defined
in a  common scheme[/b] : First, with some pre-processing the stream is
prepared for actual I/O. Then the actual I/O is done, followed by some
post-processing.

    The classes basic_istream and basic_ostream each define an auxiliary class sentry. The constructor of these classes does the preprocessing, and the destructor does the corresponding pos-tprocessing.

    If an I/O operator uses a function for unformatted I/O or operates
directly on the stream buffer, the first thing to be done should be the
construction of a corresponding sentry object.

    Its state can be checked using the conversion of the sentry object to bool

    The sentry object takes the stream strm, on which the preprocessing
and post-processing should be done, as the constructor argument.

    Of course, it is also possible to use this framework even if
functions do not use unformatted functions for their implementation but
use I/O operators
instead. However, using basic_istream or basic_ostream members for
reading or writing characters within code guarded by sentry objects is
unnecessarily expensive. Whenever possible, the corresponding
basic_streambuf should be used instead.

13.13    The Stream Buffer Classes[/b]

13.13.1    User's View of Stream Buffers[/b]

    Output Member Function

    sputc(c)
    sputn(s, n)

    The interface to reading characters from a stream buffer is a
little bit more complex. This is because for input it is necessary to
have a look at a character without consuming it. Also, it is desirable
that characters can be put back into the stream buffer when parsing.

    [/b]pubimbue() installs a new locale object in the stream buffer ,returning the previously installed locale object.
   
    [/b]getloc() returns the currently installed locale object.

13.14    Performance Issues[/b]

13.14.1    Synchronization with C's Standard Streams[/b]

    By default, the C++ standard streams  are synchronized with the corresponding files from the C standard library

13.14.2    Buffering in Stream Buffers[/b]

    The functions for formatted I/O use stream buffer iterators to
access the streams, and operating on stream buffer iterators is slower
than operating on pointers.

13.14.3    Using Stream Buffers Directly
[/b]

    All member functions of the class basic_istream and basic_ostream
that read or write characters operate according to the same schema:
First, a corresponding sentry
object is constructed, then the actual operation is performed.The
construction of the sentry object results in flushing of potentially
tied objects, skipping of whitespace (for input only), and
implementation-specific operations like locking in multithreaded
environments

    Note that a stream buffer has no error
state of its own. It also has no knowledge of the input or ouput stream
that might connect to it.

Chapter 14. Internationalization[/b]

    For the internationalization of programs, two related aspects are important

    1.    Different character sets have different properties
    2.    The user of a program expects to see national or cultural conventions obeyed
   
[/b]    The major approach toward internationalization is to use locale objects to represent an extensible collection of aspects to be adapted to specific local conventions

   
Actually, the C++ locale mechanism can be used to address all kinds of
customization, depending on the user's environment or preferences.

    Most of the mechanisms of internationalization involve no or only minimal additional work for the programmer

   
Some internationalized aspects supported by the C++ standard library
are not used by the C++ standard library itself, and to use them the
programmer has to call those functions manually.

    Strings and streams use another concept for internationalization: character traits

14.1    Different Character Encodings
[/b]
14.1.1    Wide-Character and Multibyte Text

[/b]    Two different approaches are common to address character sets that have more than 256 characters: multibyte representation and wide-character representation

    The multibyte representation is more compact than the wide-character
representation.Thus, the multibyte representation is normally used to
store data outside of programs.

    Conversely, it is much easier to process characters of fixed size, so the wide-character representation is usually used inside programs.

   
Like ISO C, ISO C++ uses the type wchar_t to represent wide characters.
However in C++, wchar_t is a keyword rather than a type definition

    During iteration through a multibyte string, each byte is interpreted according to a current "shift state[/b]"[/b].
Depending on the value of the byte and the current shift state, a byte
may represent a certain character or a change of the current shift state.

14.1.2    Character Traits[/b]
   
   
C established the convention to return a character as int instead of as
char from functions reading characters.This technique was extended in
C++. The character traits define char_type as the type to represent all characters, and int_type as the type to represent all characters plus EOF.

    The C++ standard library provides specializations of char_traits<> for types char and wchar_t

   
The specialization for char is usually implemented by using the global
string functions of C that are defined in <cstring> or
<string.h>.

14.2    The Concept of Locales

14.2.1    Using Locales

[/b]    According to X/Open conventions, the environment variable LANG is used to define the locale to be used.

    C++ provides more library support than C, because basically everything available for char is also available for wchar_t.

    The name "C" is a special name, and actually is the only locale a C++ implementation is required to support.

   
If the name used to construct a locale object is unknown to the
implementation, an exception of type runtime_error is thrown.

   
Passing an empty string as the name of the locale has a special
meaning: The default locale from the user's environment is used (this
is often determined by the environment variable LANG).

    The
static member function global()of the class locale can be used to
install a global locale object. This object is used as the default
value for functions that take an optional locale object as an argument.

   
However, setting the global locale does not replace locales already
stored in objects. It only modifies the locale object copied when a
locale is created with a default constructor.

14.2.2    Locale Facets

[/b]   
The actual dependencies on national conventions are separated into
several aspects that are handled by corresponding objects. An object
dealing with a specific aspect of internationalization is called a
facet.

    A locale object is used as a container of different facets

    The type of the facet is passed explicitly as a template argument to the template function use_facet(), accessing the desired facet.

    It is possible to define your own versions of the facets to create specialized locales.

   
To use this facet in a locale, you need to create a new locale using a
special constructor. This constructor takes a
locale object as its first argument and a pointer to a facet as its
second argument. The created locale is identical to the first argument
except for the facet that is passed as the second argument.

14.3    Locales in Detail[/b]

    A C++ locale is an immutable container for facets.

   
The strange thing about locales is how the objects stored in the
container are accessed. A facet in a locale is accessed using the type
of the facet as the index.

    Using the facet's type as an index has the additional advantage of having a type-safe interface.

    Merely copying a locale is considered to be a cheap operation. Creating a modified locale is more expensive

    The standard basically requires that two locales consisting of the same set of named facets be considered identical

14.4    Facets in Detail

[/b]    Every class F that conforms to the following two requirements can be used as a facet:

   
1.     F derives publically from class locale::facet. It  declares the copy
constructor and the assignment operator to be private, thereby making
it infeasible to copy or to assign facets

    2.     F has a publically accessible static member named id of type locale::id.

    Some special implementation guidelines
[/b]
    1.    All member functions are declared to be const
    2.    All public functions are nonvirtual and delegate each request to a protected virtual function.

Chapter 15. Allocators
[/b]

15.1    Using Allocators as an Application Programmer[/b]

    Beware that you don't mix elements with different allocators; otherwise, the behavior is undefined.

    You can check whether two allocators use the same memory model by using operator ==.

    To access the allocator, all types that are parameterized by an allocator provide the member function get_allocator().

15.2    Using Allocators as a Library Programmer[/b]

    Allocators provide an interface to allocate, create, destroy, and deallocate objects

    For the initialization of uninitialized memory the C++ standard library provides some convenience functions:

    uninitialized_fill(beg,end,val)
    uninitialized_fill_n(beg,num,val)
    uninitialized_copy(beg,end,mem)

Raw Storage Iterators

[/b]    class raw_storage_iterator is provided to iterate over uninitialized memory to initialize it.

Temporary Buffers[/b]

    get_temporary_buffer() and return_temporary_buffer().

    They are provided to handle uninitialized memory that is provided for short, temporary use inside a function

   
However, it is rather complicated to write exception-safe code with
get_temporary_buffer() and return_temporary_buffer(), so they are
usually no longer used in library  implementations

15.3    The Default Allocator

[/b]    The default allocator uses the global operators new and delete to allocate and deallocate memory

    There is a strange definition of a template structure inside the allocator, called rebind. This template structure provides the ability that any allocator may allocate storage of another type indirectly.

   
rebind<> is useful if you implement a container and you have to
allocate memory for a type that differs from the element's type

15.4    A User-Defined Allocator[/b]

    Writing your own allocator is not very hard. The most important issue is how you allocate or deallocate the storage. The rest is more or less obvious.

    Typically, the only things that differ from typical implementation are max_size(),allocate(),[/b] and deallocate().

15.6    Utilities for Uninitialized Memory in Detail

[/b]    void uninitialized_fill (ForwardIterator beg, ForwardIterator end, const T& value)

    void uninitialized_fill_n (ForwardIterator beg, Size num, const T& value)

    ForwardIterator uninitialized_copy (InputIterator sourceBeg, InputIterator sourceEnd, ForwardIterator destBeg)

    These function either succeeds or has no effect( strong exceptional safe!)
   

   

   

  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息