"C + +" Stl,vector container operations

Source: Internet
Author: User

The C + + built-in array supports the container's mechanism, but it does not support the semantics of container abstraction. To solve this problem we implement such a class ourselves. in standard C + +, it is implemented with container vectors (vector). A container vector is also a class template.
The standard library vector type uses the required header files: #include <vector>. A vector is a class template. is not a data type,vector<int> is a data type. The vector's storage space is contiguous, and the list is not stored continuously.


I. Definition and initialization
vector< typeName > v1; The default v1 is empty, so the following assignment is the wrong v1[0]=5;
Vector<typename>v2 (v1); or V2=V1; Or Vector<typename> v2 (V1.begin (), V1.end ()),//v2 is a copy of V1, if V1.size () >v2.size () is assigned V2.size () is expanded to V1.size ().
vector< typeName > V3 (n,i);//v3 a typeName type element with n values of I
vector< typeName > V4 (n); V4 contains n elements with a value of 0
int a[4]={0,1,2,3,3}; Vector<int> v5 (a,a+5); The size of//V5 is the 5 values that 5,V5 is initialized to a. The latter pointer points to the next position of the last element that will be copied.
Vector<int> V6 (V5);//v6 is a copy of V5.
vector< type > identifier (maximum capacity, initial all values).


Second, value initialization
1> If no element initialization is specified, the standard library provides itself with an initialization value for value initialization.
2> If you are saving an element of a class type that contains constructors, the standard library initializes with that type's constructor.
3> If you are saving an element of a class type that does not have a constructor, the standard library produces an object with an initial value initialized with that object.


Iii. the most important operations of vector objects
1. V.push_back (t) adds a value of t at the end of the container, and the size of the container becomes larger.
In addition the list has the Push_front () function, which is inserted at the front end, and the following elements are incremented sequentially.
2. V.size () returns the number of data in the container, and the size returns the value of the size_type defined by the corresponding vector class. V.resize (2*v.size) or

V.resize (2*v.size, 99) doubles the capacity of V (and initializes the value of the new element to 99)
3. V.empty () Determine if the vector is empty
4. V[n] Returns the element with position N in V
5. V.insert (pointer,number, content) inserts the contents of a number in the position pointed to by the pointer in V.
and V. Insert (pointer, content), V.insert (Pointer,a[2],a[4]) inserts three elements of a[2] to a[4].
6. V.pop_back () Deletes the end element of the container and does not return the element.
7.v.erase (Pointer1,pointer2) removes elements from the middle of pointer1 to Pointer2, including Pointer1.
After removing an element from the vector, the elements in this position need to move forward one position, although the current iterator position does not automatically add 1,
But because the subsequent elements are moved forward in the same way, they are equivalent to the iterator's automatic pointing to the next position.
8. V1==V2 judge whether V1 and V2 are equal.
9.! =, <, <=, >, >= keep these operators in the habit of meaning.
Vector<typename>::iterator P=v1.begin (); The P-Initial value points to the first element of the V1. *p the value of the pointed element.
For const vector<typename> can only be accessed with pointers of type Vector<typename>::const_iterator.
One. P=v1.end (); P points to the next position of the last element of the V1.
12.v.clear () deletes all the elements in the container. 12.v.clear () deletes all the elements in the container.

A functional algorithm in #include <algorithm>
Search algorithm: Find (), search (), count (), find_if (), search_if (), count_if ()
Sort by Category: sort (), merge ()
Delete algorithm: Unique (), remove ()
Generation and mutation: Generate (), fill (), Transformation (), copy ()
Relational algorithms: Equal (), Min (), Max ()
Sort (V1.begin (), Vi.begin () +V1.SIZE/2), ordering the first half of the V1
List<char>::iterator pmiddle =find (Clist.begin (), Clist.end (), ' A '), found returns the first occurrence of the checked content pointer, otherwise returns end ().
vector< typeName >::size_type x; vector< typeName > Type count, can be used for loops like for (int i)


Novice C + + programmers may think that vector subscript operations can add elements, but not:

Vector<int> Ivec; Empty vector

for (Vector<int>::size_type IX = 0; IX! = ten; ++ix)

Ivec[ix] = IX; Disaster:ivec has no elements

The above program attempts to insert 10 new elements into the Ivec, with the element values sequentially from 0 to 9 integers. However, here Ivec is an empty vector object, and the subscript can only be used to get an existing element.

The correct notation for this loop should be:

for (Vector<int>::size_type IX = 0; IX! = ten; ++ix)

Ivec.push_back (ix); Ok:adds new element with value IX


Warning: Must be an existing element to be indexed with the subscript operator. When you assign a value by using the subscript operation, no element is added. Subscript operation is only possible for elements that are known to exist

Iv. Memory management and efficiency

1. Use the reserve () function to set the size of the capacity in advance to avoid multiple capacity expansion operations resulting in inefficiency.

One of the most admirable features about STL containers is that they can automatically grow to accommodate the data you put in as long as they don't exceed their maximum size. (To know this maximum value, just call the member function called Max_size.) For vectors and strings, if more space is needed, it grows in size like realloc thought. The vector container supports random access, so in order to improve efficiency, it is implemented internally using dynamic arrays. When you request a specific size by reserve (), it always increases its internal buffer by exponential bounds. When adding elements such as insert or push_back, if the memory of the dynamic array is not enough, it is necessary to dynamically reassign the new memory area of the current size 1.5~2 times, and then copy the contents of the original array into the past. Therefore, in general, its access speed is the same as the general array, only when the reallocation occurs, its performance will be degraded. As the above code tells you. In the case of pop_back operations, the capacity does not decrease due to the decrease in the elements in the vector container, but also maintains the size before the operation. For vector containers, if there is a large amount of data to be push_back, the reserve () function should be used to set its capacity in advance, otherwise there will be many sub-capacity expansion operations, resulting in inefficient.

The reserve member function allows you to minimize the number of re-allocations that must be made, thus avoiding the overhead of true allocations and invalidation of iterators/pointers/references. But before I explain why reserve can do that, let me briefly describe some of the four related member functions that are sometimes confusing. In a standard container, only the vector and string provide all of these functions.

(1) Size () tells you how many elements are in the container. It does not tell you how much memory the container allocates for the elements it holds.
(2) capacity () tells you how many elements the container can hold in the memory it has allocated. That's how many elements a container can hold in that memory, rather than how many elements it can hold. If you want to know how much memory is not occupied in a vector or string, you must subtract size () from capacity (). If size and capacity return the same value, there is no space left in the container, and the next insertion (via insert or push_back, etc.) will cause the above redistribution step.
(3) Resize (container::size_type N) forcibly changes the container to accommodate n elements. After calling resize, size will return N. If n is less than the current size, the element at the end of the container is destroyed. If n is greater than the current size, the new default constructed element is added to the container trailer. If n is greater than the current capacity, redistribution occurs before the element is added.
(4) reserve (Container::size_type N) forces the container to change its capacity to at least N, providing n not less than the current size. This generally forces a redistribution, as capacity needs to be increased. (if n is less than the current capacity, the vector ignores it, and the call does nothing, and the string may reduce its capacity to size () and the large number in N, but the size of the string does not change.) In my experience, using the reserve to trim excess capacity from a string is generally not as good as using the "swap technique", which is the subject of clause 17. )

This profile indicates that redistribution occurs whenever there are elements that need to be inserted and the capacity of the container is insufficient (including the raw memory allocations and recoveries they maintain, the copying and destruction of objects and the invalidation of iterators, pointers, and references). Therefore, the key to avoid redistribution is to use reserve as soon as possible to set the container capacity is large enough, preferably after the container is constructed immediately.

For example, suppose you want to create a vector<int> that holds 1-1000 values. Instead of using reserve, you can do it like this:

Vector<int> v;
for (int i = 1; I <=, ++i) v.push_back (i);
In most STL implementations, this code will cause 2 to 10 reallocation during the loop. (10 This number is nothing strange.) Remember that vectors tend to double the capacity at the time of redistribution, and 1000 is approximately equal to 210. )

To change the code to use reserve, we get this:

Vector<int> v;
V.reserve (1000);
for (int i = 1; I <=, ++i) v.push_back (i);
This does not occur in the loop redistribution.

The relationship between size and capacity allows us to predict when the insertion will cause a vector or string to be reassigned, and to predict when the insertion will invalidate iterators, pointers, and references in the container. For example, given this code,

string S;
...
if (S.size () < s.capacity ()) {
S.push_back (' x ');
}
The push_back call does not invalidate the iterator, pointer, or reference that points to the string, because the capacity of the string is guaranteed to be greater than its size. If Push_back is not executed, the code makes an insert anywhere in the string, and we can still guarantee that no redistribution occurs during the insertion, but consistent with the general rule that the iterator fails when the string is inserted. All iterators/pointers/references from the insertion position to the end of the string will be invalidated.

Back to the main thrust of this article, there are usually two cases where the reserve is used to avoid unnecessary redistribution. The first available case is when you know exactly or about how many elements will eventually appear in the container. In that case, just like the vector code above, you just reserve an appropriate amount of space in advance. The second case is to keep the maximum space you may need, and then, once you've added all the data, trim out any excess capacity.

2. Use "switching technique" to trim vector excess space/memory

There is a way to reduce it from the once-largest capacity to the capacity it now needs. This way of reducing capacity is often referred to as "Shrinking to fit" (shrink to fit). The method requires only one statement:vector<int> (IVEC). Swap (IVEC);
The expression vector<int> (Ivec) establishes a temporary vector, which is a copy of the Ivec: the copy constructor of the vector does the work. However, the vector's copy constructor allocates only the memory required for the copied elements, so this temporary vector has no extra capacity. Then we let the temporary vector and the Ivec exchange data, when we finished, Ivec only the temporary variable of the trimmed capacity, and this temporary variable holds the unused excess capacity that was once in the Ivec. Here (at the end of this statement), the temporary vector is destroyed, so the memory used by the previous Ivec is freed and shrunk to fit.

3. Use the Swap method to forcibly release the memory of the STL vector

template < class t> void Clearvector (vector<t>& v)
{
vector<t>vttemp;
Vttemp.swap (v);
}
Such as
Vector<int> v;
Nums.push_back (1);
Nums.push_back (3);
Nums.push_back (2);
Nums.push_back (4);
Vector<int> (). Swap (v);

/* or V.swap (vector<int> ()); */

/* or {std::vector<int> tmp = V;   V.swap (TMP); }; The brace {} is automatically refactored when TMP exits {} */


V. Vector memory Management behavior test of member functions


The vector of C + + STL is very widely used, but the management model of its memory has been a lot of guesses, the following example code test to understand its memory management method, the test code is as follows:

#include <iostream>
#include <vector>
using namespace Std;

int main ()
{
Vector<int> IVec;
cout << "container size:" << ivec.size () << Endl;
cout << "Container capacity:" << ivec.capacity () << Endl; 1 elements with a container capacity of 1

Ivec.push_back (1);
cout << "container size:" << ivec.size () << Endl;
cout << "Container capacity:" << ivec.capacity () << Endl; 2 elements with a container capacity of 2

Ivec.push_back (2);
cout << "container size:" << ivec.size () << Endl;
cout << "Container capacity:" << ivec.capacity () << Endl; 3 elements with a container capacity of 4

Ivec.push_back (3);
cout << "container size:" << ivec.size () << Endl;
cout << "Container capacity:" << ivec.capacity () << Endl; 4 Elements with a container capacity of 4

Ivec.push_back (4);
Ivec.push_back (5);
cout << "container size:" << ivec.size () << Endl;
cout << "Container capacity:" << ivec.capacity () << Endl; 5 Elements with a container capacity of 8

Ivec.push_back (6);
cout << "container size:" << ivec.size () << Endl;
cout << "Container capacity:" << ivec.capacity () << Endl; 6 elements with a container capacity of 8

Ivec.push_back (7);
cout << "container size:" << ivec.size () << Endl;
cout << "Container capacity:" << ivec.capacity () << Endl; 7 elements with a container capacity of 8

Ivec.push_back (8);
cout << "container size:" << ivec.size () << Endl;
cout << "Container capacity:" << ivec.capacity () << Endl; 8 elements with a container capacity of 8

Ivec.push_back (9);
cout << "container size:" << ivec.size () << Endl;
cout << "Container capacity:" << ivec.capacity () << Endl; 9 elements with a container capacity of 16
/* VS2005/8 capacity growth is not doubled, such as
9 Element Capacity 9
10 Elements Capacity 13 */

/* Test the Special Swap Swap () in the effective STL */
cout << "The size of the current vector is:" << ivec.size () << Endl;
cout << "Current vector capacity:" << ivec.capacity () << Endl;
Vector<int> (IVEC). Swap (IVEC);

cout << "The size of the temporary vector<int> object is:" << (vector<int> (IVEC)). Size () << Endl;
cout << "The capacity of the temporary Vector<int> object is:" << (vector<int> (IVEC)). Capacity () << Endl;
cout << "After swapping, the current vector size is:" << ivec.size () << Endl;
cout << "After swapping, the current vector capacity is:" << ivec.capacity () << Endl;

return 0;
}

Vi. other member functions of the vector

C.assign (Beg,end)
Assigns the data in the [beg; end] Interval to C.
C.assign (N,elem)
Assigns a copy of n elem to C.
c.at (IDX)
Returns the index IDX refers to the data, if the IDX is out of bounds, throws Out_of_range.
C.back ()
Returns the last data without checking to see if the data exists.
C.front ()
Returns a data back to the ground.
Get_allocator
Use the constructor to return a copy.
C.rbegin ()
Returns the first data for a reverse queue.
C.rend ()
Returns the next position of the last data in a reverse queue.
c.~ Vector <Elem> ()
Destroys all data and frees up memory.

"C + +" Stl,vector container operations

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.