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

来源:互联网 发布:linux双网卡不同网段 编辑:程序博客网 时间:2024/05/09 05:16
C++ Standard Library, The: A Tutorial and Reference


Chap 2 Introduction to C++ and the Standard Library

2.1    history

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

   The STL was designed to combinedifferent data structures with different algorithms while achieving thebest performance. Thus, the STL is not very convenient and it is notrequired to check for many logical errors. To benefit from the powerfulframework and great performance of the STL, you must know the conceptsand apply them carefully.

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


2.2    New Language Features


2.2.1    Templates


    Non-type Template Parameters

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

    Default Template Parameters

    Templates classes may have default arguments

    Keyword Typename

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

    Member Templates

   Member functions of classes may be templates. However, member templatesmay 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 conversionswhen objects are copied. Note that a template constructor does not hidethe implicit copy constructor. If the type matches exactly, theimplicit copy constructor is generated and called.

    Nested Template Classes


2.2.2    Explicit Initialization for Fundamental Types

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


2.2.3    Exception Handling


2.2.4    Namespace

   Unlike classes, namespaces are open for definitions and extensions indifferent 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


2.2.6    Keyword explicit

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

                   
   Stack s1(40);        // OK
   Stack s2 = 40;       // ERROR

    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 explicitconversion from type X, whereas the latter creates a new object of typeY by using an implicit conversion.

2.2.8    Initialization of Constant Static Members


   It is now possible to initialize integral constant static membersinside the class structure. This is useful when the constant is used inthe 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

3.3    Error and Exception Handling

    These standard exception classes can be divided into three groups:

   1.    Exceptions for language support:

    bad_alloc            (new)
    bad_cast             (dynamic_cast)
    bad_typeid          (typeid)
    bad_exception   (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


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

    range_error
    overflow_error
    underflow_error


3.4    Allocators

   An allocator represents a special memory model. It is used asabstraction to translate the need to use memory into a raw call formemory.

    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: Only occasionally does it make sense to program  customized allocators.



Chapter 4 Utilities

4.1    class pair

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

   make_pair()

   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

   Note that class auto_ptr<> does not allow you to initialize anobject 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;    //ERROR

    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 ofownership.The const does not mean that you can't change the value ofthe object the auto_ptr owns (if any). You can't change the ownershipof a constant auto_ptr; however, you can change the value of the objectto 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 anlvalue.Thus, the auto_ptr_ref class was introduced to provide thisconvert-to-lvalue mechanism.

4.3    numeric_limits<>

    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

    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 specialimplementations for more complex types by using template specializationor function overloading.These special implementations might save timeby swapping internal members rather than by assigning the objects. Thisis the case, for example, for all standard containers and strings .

4.5    Supplementary Comparison Operators

    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>

    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, youcould not assign NULL to a pointer. This is because in C++ there is noautomatic conversion from void* to any other pointer type.



Chapter 5 STL

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

5.1    STL Components

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

5.1    Components

    Ina way, the STL concept contradicts the original idea of object-orientedprogramming: The STL separates data and algorithms rather thancombining them.


5.2    Containers

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

    Associative containers: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, 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 functionsthat in general have "good" timing.This prevents a programmer fromcalling 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 sortingcriterion is also used as the test for equality; that is, two elementsare equal if neither is less than the other.

    Container Adapters: Stack,Queue,Priority Queue.


5.3    Iterators

    fundamental operations of an iterator:

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

   In fact, each container class defines its iterator type as a nestedclass.As a result, iterators share the same interface but havedifferent types.Because the iterator is defined by the container, itsurely 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(inaccordance with "pointer arithmetic" of an ordinary pointer).Theiterators of the container classes vector and deque, and iterators ofstrings are random access iterators.


5.4    Algorithms

   Algorithms are not member functions of the container classes. Instead,they are global functions that operate with iterators.Instead of eachalgorithm being implemented for each container type, all areimplemented 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:Severalalgorithms process more than one range. In this case you usually mustdefine both the beginning and the end only for the first range. For allother ranges you need to pass only their beginnings.


5.5    Iterator Adapters

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

5.5.1    Insert Iterators

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

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

    Three predefined insert iterators:

    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:insertselements directly in front of the position that is passed as the secondargument of its initialization. It calls the insert() member functionwith the new value and the new position as arguments.For associative containers, the position is taken as a hintto start the search for the correct position. If the position is notcorrect, however, the timing may be worse than if there was no hint

5.5.2    Stream Iterators

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

5.5.3    Reverse Iterators

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

5.6    Manipulating Algorithms

5.6.1    "Removing" Elements

    The price of the flexibility of the STL:

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

5.6.2    Manipulating Algorithms and Associative Containers

    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

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

5.8    Functions as Algorithm Arguments

5.8.2    Predicates

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

5.9 Function Objects

    There are rarely things that are not possible in C++!

   It is true that functors do complicate code. However, function objectsare 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

   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

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

5.10.1    Requirements for Container Elements

    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 containersthe operations of the sorting criterion must be provided by theelements. By default, this is the operator <, which is called by theless<> function object.


5.10.2    Value Semantics or Reference Semantics

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


5.11    Errors and Exceptions Inside the STL


5.11.1    Error Handling

   The design goal of the STL was the best performance rather than themost 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

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

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

    For all node-based containers (lists,sets, multisets, maps and multimaps), any failure to construct a nodesimply 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


6.1    Common Container Abilities and Operations

    Container's constructors are member templates

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


6.2    Vectors

6.2.1    Abilities of Vectors

    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 thecapacity.Calling reserve() with an argument that is less than thecurrent capacity is a no-op.

    Only at() performs range checking   

6.2.3    Using Vectors as Ordinary Arrays

    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>.

    Better not use vector<bool>!

6.3    Deques

    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 bunchof individual blocks, with the first block growing in one direction andthe last block growing in the opposite direction.

6.4    Lists

    Lists provide many special member functions for moving elements.These member functions are faster versions of general algorithms thathave the same names. They are faster because they only redirectpointers 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

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

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

   Like all standardized associative container classes, sets and multisetsare usually implemented as balanced binary trees . Thestandard does not specify this, but it follows from the complexity ofset and multiset operations.In fact, sets and multisets are typicallyimplemented 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 parameter

        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

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

    Inserting and removing

     * 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

    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 amap and a multimap is considered to be constant.So,you can't call anymodifying algorithm if the destination is a map or multimap.


6.6.3    Using Maps as Associative Arrays

   Associative containers don't typically provide abilities for directelement 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

    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

   STL container classes provide value semantics but notreference semantics.if you want reference semantics in STLcontainers,you should use a smart pointer class that avoids possibleerrors.



Chapter 7. STL Iterators

7.2    Iterator Categories

    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 thesame 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.

    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 iteratorsare combinations of input and output iterators.Unlike input iteratorsand output iterators, forward iterators can refer to the same elementin the same collection and process the same element more than once.

    Bidirectional iterators are forward iterators that provide the additional ability to iterate backward over the
elements.

    Random access iteratorsare bidirectional iterators that are bidirectional iterators thatsupport  "iterator arithmetic". That is ,hey can add and subtractoffsets, process differences, and compare iterators with relationaloperators such as < and >

7.2.6    The Increment and Decrement Problem of Vector Iterators

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

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

7.3    Auxiliary Iterator Functions

    Three auxiliary functions for iterators: advance(), distance(), and iter_swap()

    void advance (InputIterator& pos, Dist n)

    Note that advance() does not checkwhether it crosses the end() of a sequence (it can't check becauseiterators in general do not know the containers on which they operate).Thus, calling this function might result in undefined behavior becausecalling 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

7.4.1    Reverse Iterators

    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, theiterators 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 ) VS  physical position (the element pointed to )

    Within a conversion from an iterator to a reverse iterator,physical position stays the same.

    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, butthe logical position (the value the iterator returns ) is changed.



7.4.2    Insert Iterators

    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

   The implementation of an ostream iterator uses the same concept as theimplementation 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 (asusual, reading is more complicated than writing).

    end-of-stream iterator: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

    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

8.1    The Concept of Function Objects

    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 functionobject by reference you simply have to explicitly qualify the call ofthe 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

    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

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

8.2.1    Function Adapters

    bind1st,bind2rd,not1,not2

   A function adapter is a function object that enables the combining offunction objects with each other, with certain values, or with specialfunctions.

    Function adapters are function objects themselves.

   By using function adapters you can combine different function objectsto form very powerful expressions. This kind of programming is called functional composition.

8.2.2    Function Adapters for Member Functions

    mem_fun_ref,mem_fun

   The adapter is necessary because you can't pass a member functiondirectly 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
   
    ptr_fun

8.2.4    User-Defined Function Objects for Function Adapters

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

    unary_function,binary_function

8.3    Supplementary Composing Function Objects

    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.



Chapter 9. STL Algorithms

9.2    Algorithm Overview

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

    To increase theirflexibility and power, several algorithms allow the user to passuser-defined operations, which they call internally. These operationsmight be ordinary functions or function objects. If these functionsreturn a Boolean value , they are called predicates

    The _if suffix

        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

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

    Non-modifying Algorithms

        One of the most important algorithms is for_each()

    Modifying Algorithms

        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

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

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

    Mutating Algorithms

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

    Sorting Algorithms

       Sorting algorithms are a special kind of mutating algorithm.However,sorting is more complicated and therefore     usually takes more time thansimple 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

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


9.4    The for_each() Algorithm

9.5    Nonmodifying Algorithms


Chapter 10. Special Containers

    Container Adapters:Stack,Queue,Priority queue

10.1    Stack

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

    The core interface of stack:

    push()
    pop()
    top()

    The standard class stack<> prefers speed over convenience and safety

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

    The core interface of queues:

    push()
    front()
    back()
    pop()
   
10.3    Priority Queues
   
    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 templateparameter. 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()
    top()
    pop()

    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

    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 isno 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 bitsetthat is initialized according to the bits of the integral value value.

   explicit bitset<bits>::bitset (const string& str)   Create abitset that is initialized by the string str  which may contain onlythe 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 typebitset<>::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 thatcontains the value of the bitset as a binary representation writtenwith characters '0' for unset bits and '1' for set bits

   

   
Chapter 11. Strings


11.1    Motivation

    Modern data processing is mostly string processing

    find()

    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.

    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 pitfallfor the use of strings.

    Be very careful that you always usestring::size_type and not int or unsigned for the return type when youwant 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 stringuses.(length()这个名字体现了典型的C函数strlen的风格,size()这个名字则体现了典型STL成员函数的风格)

   The function getline() is a special function to read input from streamsinto 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

    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
   
        1.    Regular expressions
        2.    Word processing (capitalization, case-insensitive comparisons)


11.2.3    Constructors and Destructors

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

11.2.4    Strings and C-Strings

    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 tomark the end of the string. The character '/0' may be part of a stringjust 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 thestring. Thus, the caller must not modify or free the memory. The returnvalue of c_str() and data() is valid only until the next call of anon-constant member function for the same string

11.2.5    Size and Capacity

    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.thisvalue usually is the maximum value of the type of the index less one.

    3.    capacity()

    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 callreserve() for strings to shrink the capacity.If the argument is lessthan the current number of characters, it is a nonbinding shrink-to-fitrequest.The default value of reserve() for string is 0. So, a call ofreserve() without any argument is always a nonbinding shrink-to-fitrequest

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


11.2.7    Comparisons

   If strings are compared by <, <=, >, or >=, theircharacters are compared lexicographically according to the currentcharacter traits.

11.2.8    Modifiers

    The specialization of swap() for strings guarantees constant complexity.

11.2.11    Searching and Finding

    All search functions have the word find inside their name.

    If the search fails, they return npos

11.2.12    The Value npos

   Be very careful when using the string value npos and its type. When youwant to check the return value always use string::size_type and not intor unsigned for the type of the return value; otherwise, the comparisonof 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 thestring) must be an unsigned integral type.Because -1 is convertedinto an unsigned integral type, npos is the maximum unsigned value ofits 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

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

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

11.2.14    Internationalization

   The character traits are provided to specify the details of how to dealwith aspects depending on the representation of a character type

11.2.15    Performance

   The standard does not specify how the string class is to beimplemented. It only specifies the interface. There may be importantdifferences in speed and memory usage depending on the concept andpriorities 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

    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 thecontainer (the string) as a whole.Thus, strings are optimized to reducethe costs of assigning and passing the whole container



Chapter 13. Input/Output Using Stream Classes

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

13.1    Common Background of I/O Streams

   class istream and ostream are instantiations of class templatebasic_istream<> and basic_ostream<>, with char as thetemplate parameter.

13.1.3    Global Stream Objects

    cin (of class istream)

    cout (of class ostream)

    cerr (of class ostream)  :No buffer
   
    clog (of class ostream):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

    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

    The class templates basic_istream<> and basic_ostream<> derive virtually 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 thedata. Actually, they don't even do the formatting! The actualformatting is delegated to corresponding facets in the locale library.

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

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


    Detailed Class Definitions


   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 alsoparameterized with the character type and a traits class.


13.2.3    Header Files

    <iosfwd>

    Contains forward declarationsfor the stream classes. This header file is necessary because it is nolonger permissible to use a simple forward declaration such as "classostream;"

    <istream>

    Contains the definitions for the classes that support input only (basic_istream<>) and for the classes that support both input and output (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 should then include the header with the complete definition.

13.3    Standard Stream Operators << and >>

    Type bool

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

    Types char and wchar_t

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

    Type char*

   A C-string (that is, a char*) is read word-wise. That is, when aC-string is being read, leading whitespace is skipped by default andthe string is read until another whitespace character or end-of-file isencountered

    Type void*

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

13.4    State of Streams

    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 notdefined whether iostate is an enumeration, a type definition for anintegral type, or an instantiation of the class bitset

    eofbit normally happens with failbit because the end-of-file condition is checked and detected when an attempt is made to read beyond end-of-file. Afterreading the last character, the flag eofbit is not yet set. The nextattempt to read a character sets eofbit and failbit, because the readfails.

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


13.4.2    Member Functions Accessing the State of Streams

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

    Note that you always haveto clear error bits explicitly.If failbit is set, each following streamoperation is a no-op until failbit is cleared explicitly.


13.4.3    Stream State and Boolean Conditions

    operator void*()
    operator !()

13.4.4    Stream State and Exceptions

    To stay backward compatible, by default, streams throw noexceptions. However, for the standardized streams, it is possible todefine, for every state flag, whether setting that flag will trigger anexception. 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

    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


    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

    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

   
13.6.1 How Manipulators Work

    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

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

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

13.7.1    Format Flags

    You can also use manipulators to set and clear format flags

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

13.7.3    Field Width, Fill Character, and Adjustment

    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() definesthe fill character that is used to fill the difference between theformatted representation of a value and the minimum field width. Thedefault fill character is a space.

13.7.4    Positive Sign and Uppercase Letters

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

13.7.7    General Formatting Definitions

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

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


13.8    Internationalization

    Each stream uses an associated locale object. The initial defaultlocale object is a copy of the global locale object at the constructiontime 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 characterset to a char (if there is no such char, def is                                returned)


13.9    File Access

   For streams that are both read and written , it is not possible toswitch arbitrarily between reading and writing .This is a restrictioninherited from C.

13.9.1    File Flags

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

    ios_base::in    ios_base::out   ios_base::binary   ios_base::append    ios_base::trunc ios_base::ate
   
    ios_base::binary configures the stream to suppress conversion ofspecial characters or character sequences such as end-of-line orend-of-file

    Whether a file is opened for reading and/or for writing is independent 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 objectare determined by the stream's class

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

    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<> 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


    The C++ standard library unfortunately does not provide thispossibility of attaching a stream to an I/O channel using filedescriptors. This is because the language is supposed to be independentof any operating system.  


13.10    Connecting Input and Output Streams

13.10.1    Loose Coupling Using tie()

    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 tiedto this stream.However, you can tie an output stream to differentstreams.

    By default, the standard input is connected tothe standard output using this mechanism. This ensures that a messageasking 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

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

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

    The advantageof this approach is that the format does not need to be restored to itsoriginal 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 flushthe buffer. To make sure that an output buffer is flushed, it has to beflushed 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 allocatedoriginally, but they do not destroy stream buffers set with rdbuf()

13.10.3    Redirecting Standard Streams

    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

    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 toforget to extract the string with the function str(), and instead towrite to the file stream directly.


13.11.2 char* Stream Classes

    The char* stream classes are retained only for backwardcompatibility.Their interface is error prone and they are rarely usedcorrectly.


13.12    Input/Output Operators for User-Defined Types

13.12.4    User-Defined Operators Using Unformatted Functions


    The I/O operators defined in the C++ standard library are definedin a  common scheme : First, with some pre-processing the stream isprepared for actual I/O. Then the actual I/O is done, followed by somepost-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 operatesdirectly on the stream buffer, the first thing to be done should be theconstruction 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 preprocessingand post-processing should be done, as the constructor argument.

    Of course, it is also possible to use this framework even iffunctions do not use unformatted functions for their implementation butuse I/O operatorsinstead. However, using basic_istream or basic_ostream members forreading or writing characters within code guarded by sentry objects isunnecessarily expensive. Whenever possible, the correspondingbasic_streambuf should be used instead.

13.13    The Stream Buffer Classes

13.13.1    User's View of Stream Buffers


    Output Member Function

    sputc(c)
    sputn(s, n)

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

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

13.14    Performance Issues

13.14.1    Synchronization with C's Standard Streams


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

13.14.2    Buffering in Stream Buffers


    The functions for formatted I/O use stream buffer iterators toaccess the streams, and operating on stream buffer iterators is slowerthan operating on pointers.

13.14.3    Using Stream Buffers Directly

    All member functions of the class basic_istream and basic_ostreamthat read or write characters operate according to the same schema:First, a corresponding sentryobject is constructed, then the actual operation is performed.Theconstruction of the sentry object results in flushing of potentiallytied objects, skipping of whitespace (for input only), andimplementation-specific operations like locking in multithreadedenvironments

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



Chapter 14. Internationalization


    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
   
    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 ofcustomization, 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 libraryare not used by the C++ standard library itself, and to use them theprogrammer has to call those functions manually.

    Strings and streams use another concept for internationalization: character traits

14.1    Different Character Encodings

14.1.1    Wide-Character and Multibyte Text


    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-characterrepresentation.Thus, the multibyte representation is normally used tostore 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".Depending on the value of the byte and the current shift state, a bytemay represent a certain character or a change of the current shift state.

14.1.2    Character Traits
   
   C established the convention to return a character as int instead of aschar from functions reading characters.This technique was extended inC++. 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 globalstring functions of C that are defined in <cstring> or<string.h>.


14.2    The Concept of Locales

14.2.1    Using Locales

    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 theimplementation, an exception of type runtime_error is thrown.

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

    Thestatic member function global()of the class locale can be used toinstall a global locale object. This object is used as the defaultvalue for functions that take an optional locale object as an argument.

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

14.2.2    Locale Facets

   The actual dependencies on national conventions are separated intoseveral aspects that are handled by corresponding objects. An objectdealing with a specific aspect of internationalization is called afacet.

    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 aspecial constructor. This constructor takes alocale object as its first argument and a pointer to a facet as itssecond argument. The created locale is identical to the first argumentexcept for the facet that is passed as the second argument.

14.3    Locales in Detail

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

   The strange thing about locales is how the objects stored in thecontainer are accessed. A facet in a locale is accessed using the typeof 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

    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 copyconstructor and the assignment operator to be private, thereby makingit 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

    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


15.1    Using Allocators as an Application Programmer

    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

    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

    class raw_storage_iterator is provided to iterate over uninitialized memory to initialize it.

Temporary Buffers

    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 withget_temporary_buffer() and return_temporary_buffer(), so they areusually no longer used in library  implementations


15.3    The Default Allocator

    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 toallocate memory for a type that differs from the element's type


15.4    A User-Defined Allocator

    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(), and deallocate().


15.6    Utilities for Uninitialized Memory in Detail

    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!)