A container holds a collection of objects of a particular type.
The standard library vector type is a sequential container. It aggregates a single type element called a container, and then stores and accesses the elements based on their location, which is the sequential container. The order of the elements in a sequential container is independent of the element value, but is determined by the order in which the elements are added to the container.
The standard library defines three sequential container types: vector, list, and deque. They differ in the way that elements are accessed, as well as the operating costs associated with adding or removing elements. The standard library also provides three kinds of container adapters. In fact, the adapter is based on the operation provided by the original container type and adapts to the underlying container type by defining a new operating interface.
Sequential container type
Sequential container |
|
Vector |
Supports fast random access |
List |
Fast Insert/Delete support |
Deque |
Dual-ended queues |
Sequential container Adapters |
|
Stack |
Last in, first out (LIFO) stacks |
Deque |
First In, Out (FIFO) queue |
Priority_quede |
Priority-managed queues |
A container defines only a small number of operations. Most of the additional operations are provided by the algorithm library. The standard library imposes a common interface for operations defined by the container type. The difference between these container types is what they provide, but if two containers provide the same operation, their interfaces (the function name and the number of arguments) should be the same. The set of operations for a container type forms the following hierarchy:
1. Some operations apply to all container types.
2. Some other operations are only applicable to sequential or associative container types.
3. There are also some operations that apply only to a subset of the sequence or associated container type.
First, the definition of the sequential container
All containers are class templates. To define a particular container, you must add a pair of angle brackets after the container is clear, and the angle brackets provide the type of elements that are stored in the container.
All container types Define a default constructor that creates an empty container object of the specified type. The default constructor takes no arguments.
Note: In order to make the program clearer and shorter, the most common constructor for a container type is the default constructor. In most programs, using the default constructor achieves optimal run-time performance and makes the container easier to use.
1.1 Initialization of the container element
In addition to the default constructor, the container type provides additional constructors that allow programmers to specify the initial value of the element.
Container constructors
C<t> C; |
Create an empty container named C. C is the name of the container type, such as Vector,t is an element type, such as int or string. Applies to all containers. |
C c (C2); |
Create a copy of the container C2 c;c and C2 must have the same container type and hold elements of the same type. Applies to all containers. |
c C (b, E); |
Create C, whose elements are copies of the elements in the range indicated by iterators B and E. Use with all containers. |
c c (n, t); |
Create a container c with n values of T, where the value T must be a value of the element type of container type C, or a value that can be converted to that type, only for sequential containers |
c c (n); |
Create container C with n values to initialize elements, only for sequential containers |
1.1.1 Initializes a container to a copy of another container
When you do not use the default constructor, but instead initialize the sequential container with a different constructor, you must indicate how many elements the container has, and provide the initial values for those elements. One way to specify both the number of elements and the initial value is to initialize the newly created container to a copy of the existing container of the same type.
1.1.2 Initialized to a copy of an element
Although it is not possible to directly copy elements from one container to another, the system allows this functionality to be implemented indirectly by passing a pair of iterators. The same container type is not required when using iterators. The types of elements within a container can also be different, so as long as they are compatible with each other, replication can be achieved by converting the elements that will be copied to the element type of the new container being built.
Iterators mark the range of elements to be copied, which are used to initialize the elements of the new container. The iterator marks the first and last element to be copied.
1.1.3 Assigning and initializing a specified number of elements
When you create a sequential container, you can display the specified container size and an (optional) element initializer. The container size can be a constant or a const expression, and an element initializer must be a value that can be used to initialize an object of its element type.
When you create a container, you can choose whether to provide an element initializer, in addition to specifying the number of elements.
1.2 Type constraints for elements within a container
In the C + + language, most types are available as element types for containers. A container element type must meet the following two constraints:
1, the element type must support the assignment operation;
2. An object of the element type must be replicable.
1.2.1 Special requirements for container operation
Support for assignment and replication is the minimum requirement for container element types. In addition, some container operations have special requirements for element types. If the element type does not support these special requirements, then the associated container operation cannot be performed: we can define containers of that type, but we cannot use certain actions.
Containers for 1.2.2 Containers
Because the container is constrained by the container element type, the definable element is a container of the container type.
Second, iterator and iterator range
In the entire standard library, formal parameters are often used as constructors for a pair of iterators.
Each type of container provides several iterator types that work together. As with the container type, all iterators have the same interface: if some kind of iterator supports an operation, other iterators that support it will also support the operation in the same way.
Common iterator operations
*iter |
Returns a reference to the element pointed to by the iterator ITER |
Iter->mem |
A dereference of ITER gets the member named MEM in the specified element. Equivalent to (*iter). Mem |
++iter |
Add 1 to ITER so that it points to the next element in the container |
iter++ |
Add 1 to ITER so that it points to the next element in the container |
--iter |
Reduce 1 to ITER to point to the previous element in the container |
iter-- |
Reduce 1 to ITER to point to the previous element in the container |
Iter1 = = Iter2 |
Compares whether two iterators are equal (or unequal). When two iterators point to the same element in the same container, or when they are Two iterators are equal when pointing to the next position of the same container beyond the end |
Iter1! = Iter2 |
Compares whether two iterators are equal (or unequal). When two iterators point to the same element in the same container, or when they are Two iterators are equal when pointing to the next position of the same container beyond the end |
An iterator to the vector and Deque containers provides additional operations
Of the container types defined by C + +, only the vector and deque containers provide the following two important sets of operations: an iterator arithmetic operation, and a relational operator that uses = = and! = To compare two iterators (= = and! =) for all containers.
Supported operations for vector and deque type iterators
Iter+n |
adding (minus) An integer value n on an iterator produces an iterator that points to the nth element in the container in front (followed). The newly computed iterator must point to the element in the container or to the next position at the end of the container. |
Iter-n |
adding (minus) An integer value n on an iterator produces an iterator that points to the nth element in the container in front (followed). The newly computed iterator must point to the element in the container or to the next position at the end of the container. |
Iter1 + = Iter2 |
This is the compound assignment operation for the addition and subtraction of iterators: Assigning the results of Iter1 plus or minus iter2 to Iter1 |
Iter1-= Iter2 |
This is the compound assignment operation for the addition and subtraction of iterators: Assigning the results of Iter1 plus or minus iter2 to Iter1 |
Iter1-iter2 |
The subtraction of two iterators, and the result of the operation plus the iterator on the right is the iterator to the left. These two iterators must be Must point to an element in the same container or to the next position beyond the end of the container. For vector and deque containers only |
, >=, <, <= |
The relationship operator for the iterator. When an iterator points to an element that is in the container before another iterator points to an element, The previous iterator is less than the latter one. The two iterators of the relational operator must point to the elements in the same container Or the next position beyond the end of the container. For vector and deque containers only |
The relational operators only apply to vectors and deque containers, only because these two containers provide fast, random access to their elements. They ensure that the specified container elements are accessed directly and efficiently based on the location of the element. Both support random access through element locations, so their iterators can effectively implement arithmetic and relational operations.
2.1 Iterator Range
The C + + language uses a pair of iterators to tag the iterator scope. The two iterators point to two elements in the same container or to the next position beyond the end, usually named first and last, or beg and end, to mark a range of elements in the container.
Note: Requirements for iterators that form an iterator range:
Iterators first and last can form an iterator range if the following conditions are true:
1. They point to an element in the same container or to the next position beyond the end.
2, if the two iterators are not equal, then the first iteration of the self-increment operation must be able to reach the last. In other words, in a container, last must never precede first.
Programmatic significance of using left closed interval
Because the left-closing interval has two convenient properties, the standard library uses such a range. Assuming that first and last mark a valid iterator range, then:
(1), when first and last are equal, the range of iterators is empty;
(2), when first and last are not equal, there is at least one element within the iterator range, and firstly points to the element in the interval. In addition, the value of first can be increased by several times of self-increment, knowing First==last.
2.2 Container operations that invalidate iterators
When you write a program using iterators, you must be aware of what actions will invalidate the iterator. Using an invalid iterator will result in a serious run-time error.
When using iterators, you can often write programs that require a relatively short range of code that requires an iterator to be valid. Then, within that range, each statement is strictly checked to determine if an element is added or deleted, thereby adjusting the value of the iterator accordingly.
Third, the operation of the sequential container
Each of these sequential containers provides a useful set of type definitions and operations:
1. Adding elements to the container
2. Delete the element in the container.
3, set the size of the container.
4, (if any) gets the first and last element within the container.
3.1 container-defined type aliases
container-defined type aliases
Size_type |
unsigned integer, sufficient to store the maximum possible container length for this container type |
Iterator |
The type of iterator for this container type |
Const_iterator |
Read-only iterator type for element |
Reverse_iterator |
Iterator addressing elements in reverse order |
Const_reverse_iterator |
Element's read-only (cannot write) reverse iterator |
Difference_type |
A signed integer sufficient to store two iterator differences, which can be negative |
Value_type |
Element type |
Reference |
The left value type of the element, which is a synonym for value_type& |
Const_reference |
The constant lvalue type of the element, equivalent to the const value_type& |
3.2 Begin and end members
The Begin and end operations produce iterators that point to the next position of the first and last elements within a container. These two iterators are typically used to mark all element iterator ranges in the containing container.
Begin and end operations for containers
C.begin () |
Returns an iterator that points to the first element of container C |
C.end () |
Returns an iterator that points to the next position of the last element of container C |
C.rbegin () |
Returns an inverse iterator that points to the last element of container C |
C.rend () |
Returns an inverse iterator that points to the position in front of the first element of container C |
Each of these operations has two different versions: one is a const member and the other is a non-const member.
What types these operations return depends on whether the container is const. If the container is not const, these operations return the iterator or reverse_iterator type. If the container is const, its return type is prefixed with the const_ prefix, which is the const_iterator and const_reverse_iterator types.
3.3 Adding elements to a sequential container
Actions to add elements to a sequential container
C.push_back (t) |
Adds an element with a value of t at the tail of container C. return void type |
C.push_front (t) |
Add an element with a value of t at the front end of container c. return void type Only available for list and deque container types |
C.insert (P, t) |
Inserts a new element with a value of t before the element that the iterator p points to. Returns an iterator that points to the newly added element |
C.insert (P, N, T) |
Inserts a new element with n values of T before the element that the iterator p points to. return void type |
C.insert (p, B, E) |
Inserts an element in the range labeled by Iterators B and E before the element that the iterator p points to. Returns the void type. |
Key concepts: container elements are replicas
When you add elements to a container, the system copies the element values into the container. Similarly, when a new container is initialized with a section of elements, the new container holds a copy of the original element. The original value being copied is not related to the elements in the new container, and thereafter, when the value of the element in the container changes, the copied original value is not affected, and vice versa.
3.3.1 Add an element at the specified position in the container
3.3.2 Inserting a section of an element
3.3.3 adding elements may invalidate iterators
Adding an element to a vector container may cause the entire container to reload, so that all iterators involved in the container will be invalidated. Even if the entire container needs to be reloaded, the iterator that points to the element that follows the newly inserted element is invalidated.
Note: Any insert or push operation can cause an iterator to fail. When writing loops to insert elements into a vector or deque container, the program must ensure that the iterator is updated after each loop.
3.3.4 avoid storing the iterator returned by the end operation
When you add elements to a vector or deque container, some or all of the iterators may be invalidated. It is the safest practice to assume that all iterators fail. This recommendation is particularly useful for iterators returned by the end operation. Inserting any element anywhere in the container invalidates the iterator.
3.4 Relational operators
All container types support the use of relational operators to make comparisons between two containers. The container that you compare must have the same container type, and its element type must be the same.
The comparison of containers is based on the comparison of elements within the container. The container comparison uses the same relational operator defined by the element type: two containers do! = comparison uses the! = Operator for its element type definition. If the element type of the container does not support an operator, then the class container cannot do this kind of comparison operation.
The following operation is similar to a string type of relational operation:
1, if two containers have the same length and all elements are equal, then the two containers are equal; otherwise, they are not equal.
2, if the length of the two containers is not the same, but the shorter container all the elements are equal to the corresponding elements in the longer container, it is said that the shorter container is smaller than the other container.
3. If none of the two containers are the initial subsequence of each other, their comparison will depend on the first unequal element being compared.
Use the relational operator provided by the element to implement the container's relational operations:
The C + + language allows only two containers to do relational operations with their element type definitions.
All containers implement relational operations by comparing their element pairs.
3.5 container-sized operations
All container types provide four container-size-related operations.
The size of the sequential container operation
C.size () |
Returns the number of elements in container C. return type is C::size_type |
C.max_size () |
Returns the maximum number of elements that container C can hold, with a return type of C::size_type |
C.empty () |
Returns a Boolean value that marks whether the container size is 0 |
C.resize (N) |
Adjusts the length of the container C so that it can hold n elements, and if N<c.size (), remove the extra elements; otherwise, add a new element with the value initialization. |
C.resize (n, T) |
Adjusts the length of container C so that it can hold n elements. All newly added element values are t. |
3.6 Accessing elements
If the container is not empty, then the front and back members of the container type will return a reference to the first or last element within the container.
C + + Primer Fourth Edition reading notes (eight) Order container