《C++ Primer第五版》读书笔记(7)--SEQUENTIAL CONTAINERS

来源:互联网 发布:python http上传文件 编辑:程序博客网 时间:2024/05/21 07:56
9 SEQUENTIAL CONTAINERS
9.1 OVERVIEW OF THE SEQUENTIAL CONTAINERS
A container holds a collection of objects of a specified type. The sequential containers let the programmer control the order in which the elements are stored and accessed.The order of the elements in a sequential container corresponds to the positions in which the elements are added to the container.
Sequential Container Types
 
The new library containers are dramatically faster than in previous releases. The library containers almost certainly perform as well as (and usually better than) even the most carefully crafted alternatives. Modern C++ programs should use the library containers rather than more primitive structures like arrays.
There are a few rules of thumb that apply to selecting which container to use:
• Unless you have a reason to use another container, use a vector.
• If your program has lots of small elements and space overhead matters, don’t use listor forward_list.
•If the program requires random access to elements, use a vector or a deque.
•If the program needs to insert or delete elements in the middle of the container, use a listor forward_list.
•If the program needs to insert or delete elements at the front and the back, but not in the middle, use a deque.
•If the program needs to insert elements in the middle of the container only while reading input, and subsequently needs random access to the elements:
–First, decide whether you actually need to add elements in the middle of a container. It is often easier to append to a vectorand then call the library sort to reorder the container when you’re done with input.
–If you must insert into the middle, consider using a list for the input phase. Once the input is complete, copy the list into a vector.
If you’re not sure which container to use, write your code so that it uses only operations common to both vectors and lists: Use iterators, not subscripts, and avoid random access to elements. That way it will be easy to use either a vectoror a list as necessary.
9.2 CONTAINER LIBRARY OVERVIEW
Some operations are provided by all container types:
 


9.2.1 ITERATORS
The exception is that the forward_list iterators do not support the decrement (--) operator. 
An iterator range is denoted by a pair of iterators. These two iterators, often referred to as begin and end—or (somewhat misleadingly) as first and last—mark a range of elements from the container. 
This element range is called a left-inclusive interval:
[ begin, end)
9.2.2 CONTAINER TYPE MEMBERS
If we need the element type, we refer to the container’s value_type. If we need a reference to that type, we use reference or const_reference.
9.2.3 BEGIN AND END MEMBERS
In the past, we had no choice but to say which type of iterator we want. The c versions were introduced by the new standard to support using autowith begin and end functions:
// type is explicitly specified
list<string>::iterator it5 = a.begin();
list<string>::const_iterator it6 = a.begin();
// iterator or const_iterator depending on a's type of 
auto it7 = a.begin();  // const_iterator only if a is const
auto it8 = a.cbegin(); // it8 is const_iterator
The c versions let us get a const_iteratorregardless of the type of the container.
9.2.4 DEFINING AND INITIALIZING A CONTAINER
Library arrays Have Fixed Size:
array<int,42>  // type is: array that holds 42 ints
array<string, 10> // type is: array that holds 10 strings
To use an arraytype we must specify both the element type and the size:
array<int, 10>::size_type i; // array type includes element type and size
array<int>::size_type j;  // error: array<int> is not a type
9.3 SEQUENTIAL CONTAINER OPERATIONS
9.3.1 ADDING ELEMENTS TO A SEQUENTIAL CONTAINER
Operations That Add Elements to a Sequential Container
 
// construct a Sales_data object at the end of c
// uses the three-argument Sales_data constructor
c.emplace_back("978-0590353403", 25, 15.99);
// error: there is no version of push_back that takes three arguments
c.push_back("978-0590353403", 25, 15.99);
// ok: we create a temporary Sales_data object to pass to push_back
c.push_back(Sales_data("978-0590353403", 25, 15.99));
9.3.2 ACCESSING ELEMENTS
 
9.3.3 ERASING ELEMENTS
 
9.3.4 SPECIALIZED FORWARD_LIST OPERATIONS
When we add or remove an element, the element before the one we added or removed has a different successor. To add or remove an element, we need access to its predecessor in order to update that element’s links. However, forward_list is a singly linked list. In a singly linked list there is no easy way to get to an element’s predecessor.
For this reason, the operations to add or remove elements in a forward_listoperate by changing the element afterthe given element. forward_list does not define insert, emplace, or erase. Instead it defines members  named insert_after, emplace_after, and erase_after.
9.3.5 WRITING LOOPS THAT CHANGE A CONTAINER
Loops that add or remove elements of a vector, string, or deque must cater to the fact that iterators, references, or pointers might be invalidated. The program must ensure that the iterator, reference, or pointer is refreshed on each trip through the loop. Refreshing an iterator is easy if the loop calls insertor erase.
// safer: recalculate end on each trip whenever the loop adds/erases elements
while (begin != v.end()) {
// do some processing
++begin;  // advance begin because we want to insert after this element
begin = v.insert(begin, 42);  // insert the new value
++begin;  // advance begin past the element we just added
}
9.4 ADDITIONAL STRING OPERATIONS
9.4.1 SUBSTR
 
 
9.5 CONTAINER ADAPTORS
In addition to the sequential containers, the library defines three sequential container adaptors:stack, queue, and priority_queue. A container adaptor takes an existing container type and makes it act like a different type. For example, the stack adaptor takes a sequential container (other than array or forward_list) and makes it operate as if it were a stack.
Operations and Types Common to the Container Adaptors:
 
By default both stack and queue are implemented in terms of deque, and a priority_queue is implemented on a vector.
We can override the default container type by naming a sequential container as a second type argument when we create the adaptor:
// empty stack implemented on top of vector
stack<string, vector<string>> str_stk;
// str_stk2 is implemented on top of vector and initially holds a copy of svec
stack<string, vector<string>> str_stk2(svec);
There are constraints on which containers can be used for a given adaptor. All of the adaptors require the ability to add and remove elements. As a result, they cannot be built on an array. Similarly, we cannot use forward_list, because all of the adaptors require operations that add, remove, or access the last element in the container.
A stack requires only push_back, pop_back, and back operations, so we can use any of the remaining container types for a stack. The queue adaptor requires back, push_back, front, and push_front, so it can be built on a list or deque but not on a vector. A priority_queue requires random access in addition to the front, push_back, and pop_back operations; it can be built on a vector or a deque but not on a list.
Stack Adaptor:
 
The Queue Adaptors(queue &priority_queue) :
 
The library queue uses a first-in, first-out (FIFO) storage and retrieval policy. Objects entering the queue are placed in the back and objects leaving the queue are removed from the front.
A priority_queue lets us establish a priority among the elements held in the queue. Newly added elements are placed ahead of all the elements with a lower priority.
0 0