Use of the vector of the STL
Getting started with the first part
Vectors can be used instead of arrays in C, or CArray in MFC, from many explanatory documents or online comments, and generally agree that vectors should be used more efficiently and with exceptional security. And vectors are the default containers recommended by STL, unless you know you have special needs, using vectors that do not meet your needs, such as requiring containers to be efficiently inserted and removed at head and tail, or efficiently removed and inserted in any location, Then you might use deque or list more appropriately.
Vectors are contiguous memory containers, in other words, when standards require all standard libraries to be implemented, the memory of elements in a vector must be contiguous. So the time complexity for insertions and deletions is very high, because when you delete or INSERT, you need to move the element, that is, the copy of the element.
The internal implementation of vectors generally needs to use the placement new, so the efficiency is very high, because many times, as long as we are used to get, we can save a lot of memory allocation overhead. and the use of vectors, elements can have no default constructor, but need to copy the existence of the constructor, which is not possible with the use of CArray.
principle of Use:
1, try to use vectors instead of C-style arrays or carray;
2, try to use algorithms instead of hand-written loops;
3, try to use the function of vector itself instead of other generic algorithms;
Vector interface is easy to understand and use, here are some examples to illustrate the use of vectors.
1, filled vector
If we want to populate the vector with the contents of the original array, there are many ways. Let's take a few methods of learning vectors.
For example we have array int v1[10] = {0,1,0,0,3,0,0,4,4,4};
initialization Mode 1:
Vector<int> v2 (10); Initializing a size of 10 avoids the constant allocation of memory when the array is dynamically growing
V2.reserve (10);//ditto, just use one of them.
for (int i=0; i<10; i++)
{
V2.push_back (V1[i]);//Add an element
}
initialization Mode 2:
Vector<int> v3 (&v1[0],&v1[9]);//The element pointer of the original array can be used as an iterator
initialization mode 3:
Vector<int> v4;
V4.reserve (10);
V4.insert (V4.begin (), &v1[0], &v[9]);
initialization Mode 4:
Vector<int> v5 (10);
Copy (V5.begin (), &v1[0], &v1[9]);
The element pointer of the original array can be used as an iterator.
principle: Use reserve as much as possible to reduce the number of unnecessary memory allocations.
principle: Try to use empty instead of size () ==0 to determine if the container is empty
It's possible that we need to insert the appropriate element in the vector.
Vector<int>::iterator i = Find (V1.begin (), V1.end (), 3);
if (i! = V1.end ())
{
V1.insert (i, 6);
}
2, traversing vector
For example there are vector<int> v1;
void print (int i)
{
cout << i << Endl;
}
Mode 1:
for (int i=0; i<v1.size (); i++)
{
Print (V1[i]);
}
This is the way we are most familiar with, but not good enough to write concise enough. And for other containers that do not have random iterators, this is impossible.
Mode 2:
typedef vector<int>:: iterator Vintiterator;
Vintiterator end = V1.begin ();
For (Vintiterator i=v1.begin (); I! = end; ++i)
{
Print (*i);
}
Note: It is advantageous to calculate end first, because it is not necessary to repeat the calculation of the End,vector end () every time, so caching it first can improve efficiency. When writing algorithms, try to use! = to compare iterators, because < does not have this operator for many non-random iterators.
But this kind of way is also more cumbersome to write.
Mode 3:
For_each (V1.begin (), V1.end (), print);
Using algorithms is a lot easier to write.
When using algorithms, you can use function objects, such as
Class OutPut
{
Public
void operator () (double i)
{
Std::cout << i;
}
}
For_each (V1.begin (), V1.end (), OutPut);
Delete in 3,vector
Delete the specified element
Vector<double> v1;
.... Initialize code
Vector<double>:: Iterator i = Find (V1.begin (), V1.end (), 3.0);
if (i! = V1.end ())
{
V1.erase (i);
}
Does this really delete the specified element? No. In fact, only the internal elements have been moved, the time complexity of the deletion of vectors is very high. So when choosing a container, if you need to insert and delete elements frequently in the middle, choosing a vector will affect efficiency.
Note: An INSERT or delete operation invalidates the iterator.
principle: Delete elements using Erase-remove idioms
V1.erase (Remove (V1.begin (), V1.end (), 3.0), v1.end ());
whether the 4,vector is empty
When judging if the container is empty, use empty () instead of size () for 0 inspection, because empty is more efficient time complexity is constant time, and size () time complexity is not constant time.
Principle: Use empty to determine if the standard container is empty
Find in 5,vector
Principle: Try to replace the common algorithm with the standard container's own algorithm.
But Vector does not have many of its own algorithms, but the list has a remove, remove_if,sort,reverse and other algorithms.
Find
Find_if
6, using switching techniques to correct excess capacity
Vector<int> v1;
... Initialize V1
... Delete all the elements in the V1
But this time V1 memory capacity is not 0, or a large piece of memory is not released, if you want to empty
Use V1.reserve (0) to reach the target, because reserve can only enlarge the memory capacity and cannot be reduced.
Vector<int> v2;
V2.swap (v1);
This is the time to really reduce the memory capacity to a minimum.
6, off-topic: Using Algorithms and other tricks
principle: Do not use auto_ptr as a template parameter to build the container, this will produce unexpected traps, because the copy of auto_ptr has special semantics
principle: Avoid using VECTOR<BOOL>, because it cannot be used as a standard container
Copy
Find_if
For_each
principle: Try to use interval member functions instead of their single-element parameter sibling member functions
Interval construction
Interval Delete
Interval Assignment
Interval insertion
principle: The copy operation of the elements in the container is lightweight and correct, the copy is the basic way of the container in the STL, the element is added to the container, and the element in the container is no longer the original element, so if the pointer is added to the container, The object that the pointer refers to must be deleted before the container leaves the scope.
void Fun ()
{
Vector<object*> v1;
...//insert operation
For (vector<object*>:: Iterator i = V1.begin (); I! = V1.end (); ++i)
{
Delete *i;
}
}
principle: Note for vectors, any insert delete operation will invalidate the iterator. So be careful.
The second part uses the error discussion
Vector semantics are often misunderstood, so the use of errors often occurs
1, Case one
Can you find the following problem?