This article on the introduction of STL vector usage is very detailed, please see below
Introduced
The purpose of this article is to introduce std::vector, how to properly use their member functions, and so on. The use of conditional functions and function pointers in iterative algorithms, such as in Remove_if () and For_each (), is also discussed in this paper. By reading this article readers should be able to use vector containers effectively, and should no longer use a dynamic array of type C.
Vector overview
Vector is part of the C + + Standard Template Library, a versatile template class and function library that can manipulate a variety of data structures and algorithms. Vector is considered a container because it can hold various types of objects like a container, simply put, vector is a dynamic array of any type that can be stored to add and compress data.
In order to be able to use vectors, you must include the following code in your header file:
Vectors belong to the STD-named domain, so you need to have a naming qualification to complete your code as follows:
Using Std::vector;
Vector<int> vints;
Or even together, using the full name:
Std::vector<int> vints;
It is recommended that you use the global named Domain method:
using namespace Std;
The global naming domain method in subsequent operations can cause problems. The vector container provides a number of interfaces that list the vector's member functions and operations in the table below.
Vector member functions
Function |
Expression |
C.assign (Beg,end) C.assign (N,elem) |
will be [Beg end] the data assignment in the interval is given to C . will be N a Elem the copy assignment to C . |
c.at (IDX) |
return Index idx refers to the data, if idx Out of bounds, thrown Out_of_range . |
C.back () |
Returns the last data and does not check if the data exists. |
C.begin () |
Returns the iterator's one-valued data. |
C.capacity () |
Returns the number of data in a container. |
C.clear () |
Removes all data from the container. |
C.empty () |
Determines whether the container is empty. |
C.end () |
Point to the last data address in the iterator. |
C.erase (POS) C.erase (Beg,end) |
Remove POS position, and returns the location of the next data. Remove [Beg,end) interval data, which returns the location of the next data. . |
C.front () |
Returns the first data. |
Get_allocator |
Returns a copy using the constructor. |
C.insert (Pos,elem) C.insert (Pos,n,elem) C.insert (Pos,beg,end) |
in the POS position to insert a Elem copy and return the new data location. in the POS Position Insertion N a Elem data. no return value. in the POS position is inserted in the [Beg,end) interval of data. no return value. |
C.max_size () |
Returns the maximum number of data in the container. |
C.pop_back () |
Deletes the last data. |
C.push_back (Elem) |
Add a data to the tail. |
C.rbegin () |
Returns the first data of a reverse queue. |
C.rend () |
Returns the next position of the last data in a reverse queue. |
C.resize (num) |
Re-specify the length of the queue. |
C.reserve () |
Keep the appropriate capacity. |
C.size () |
Returns the number of actual data in the container. |
C1.swap (C2) Swap (C1,C2) |
will be C1 and C2 element Interchange. Ditto operation. |
Vector<elem> C Vector <Elem> C1 (C2) Vector <Elem> C (n) Vector <Elem> C (n, Elem) Vector <Elem> C (beg,end) c.~ Vector <Elem> () |
Create an empty Vector . Copy a Vector . Create a Vector , containing N data, the data has been constructed by default . Create a containing N a Elem copy of Vector . Create a to [Beg;end) Interval of Vector . Destroys all data and frees up memory. |
Vector operations
Function |
Describe |
operator [] |
Returns a reference to the specified position in the container. |
Create a vector
Vector containers provide a variety of ways to create, and here are a few common.
To create an empty vector object of the widget type:
Vector<widget> vwidgets;
// ------
// | | |-Since vector is a container, it member functions
//operate on iterators and the container
// It can hold objects of any type.
Create a vector that contains 500 widget type data:
Vector<widget> Vwidgets (500);
Creates a vector that contains 500 widget type data and is initialized to 0:
Vector<widget> vwidgets, Widget (0));
Create a copy of the widget:
Vector<widget> Vwidgetsfromanother (vwidgets);
Add a data to the vector
The vector's default method for adding data is push_back (). The Push_back () function represents adding data to the tail of the vector and allocating memory as needed. For example, to add 10 data to the vector<widget>, you need to write the following code:
for (int i= 0;i<10; i++)
vwidgets.push_back (Widget (i));
Get the data in the vector where the location is drawn
Many times we don't need to know how much data is in the vector, the data in the vector is dynamically allocated, and a series of allocated spaces using push_back () are often determined by the file or some data source. If you want to know how much data the vector holds, you can use empty (). Gets the size of the vector, you can use size (). For example, if you want to get the size of a vector v, but you don't know if it's empty, or if you've already included the data, if you set it to 1, you can use the following code to implement:
int nsize = V.empty ()? -1:static_cast<int> (V.size ());
Accessing data in a vector
Use two methods to access the vector.
1, Vector::at ()
2, vector::operator[]
Operator[] is primarily intended to be compatible with the C language. It can operate like an array of C languages. But at () is our preferred option because at () has a boundary check and if the access exceeds the vector range, an exception will be thrown. Because operator[] is prone to making some errors, all of us rarely use it, and the following is validated:
Analyze the following code:
Vector<int> v;
V.reserve (ten);
for (int i=0; i<7; i++)
v.push_back (i);
Try
{
int iVal1 = v[7];//not bounds Checked-will not throw
int iVal2 = v.at (7);//bounds Checked-will t Hrow if out of range
}
catch (const exception& e)
{
cout << e.what ();
}
We used the reserve () to allocate 10 int space, but not uninitialized.
You can try different conditions in this code, observe its results, but whenever you use at (), it is correct.
Delete data in a vector
Vectors can be very easy to add data, and can easily take out data, the same vector provides erase (), Pop_back (), clear () to delete data, when you delete data, you should know to delete the tail of the data, or delete all the data, or the individual data. Let's think about some of the applications in the STL before we consider the deletion and other operations.
REMOVE_IF () algorithm
Now we consider the data inside the operation. If you want to use REMOVE_IF (), we need to include the following code in the header file::
#include <algorithm>
remove_if () has three parameters:
1, iterator _first: An iterative pointer to the first data.
2, iterator _last: An iterative pointer to the last data.
3. Predicate _pred: A conditional function that can operate on an iteration.
Conditional function
A conditional function is a result that returns Yes or no according to a user-defined condition, is the most basic function pointer, or is a function object. This function object needs to support all function invocation operations, overloading the Operator () () operation. Remove_if () is inherited through unary_function, allowing data to be passed as a condition.
For example, if you want to remove a matching data from a vector<cstring>, if the string contains a value, start at this value and end with that value. First you should set up a data structure to contain these, similar to the following code:
#include <functional>
enum findmodes
{
fm_invalid = 0,
fm_is,
fm_startswith,
fm_ ENDSWITH,
fm_contains
};
typedef struct TAGFINDSTR
{
UINT imode;
CString szmatchstr;
} FINDSTR;
typedef findstr* LPFINDSTR;
Then the processing conditions are judged:
Class findmatchingstring
: Public std::unary_function<cstring, bool>
{public
:
findmatchingstring (const LPFINDSTR LPFS): M_lpfs (LPFS) {}
bool operator () (cstring& szstringtocompare) const
{
bool retVal = false;
Switch (M_lpfs->imode)
{case
fm_is:
{
RetVal = (Szstringtocompare = = m_lpfdd->szmatchstr) ;
break;
Case Fm_startswith:
{
retVal = (Szstringtocompare.left (m_lpfdd->szmatchstr.getlength ())
= = M_ Lpfdd->szwindowtitle);
break;
Case Fm_endswith:
{
retVal = (Szstringtocompare.right (m_lpfdd->szmatchstr.getlength ())
= = M_ LPFDD->SZMATCHSTR);
break;
Case Fm_contains:
{
retVal = (Szstringtocompare.find (m_lpfdd->szmatchstr)!=-1);
break;
}
}
return retVal;
}
Private:
lpfindstr M_lpfs;
In this way you can effectively delete data from vectors:
Remove all strings containing the value of
//Szremove from vector<cstring> vs.
FindStr FS;
Fs.imode = Fm_contains;
Fs.szmatchstr = Szremove;
Vs.erase (Std::remove_if (Vs.begin (), Vs.end (), findmatchingstring (&FS)), Vs.end ());
Remove_if () What can be done?
You might wonder, for the above example, to use erase () when calling remove_if ()? This is because you are not familiar with the algorithms in STL. Remove (), remove_if (), and so on all the removal operations are based on an iterative scope, then can not manipulate the data in the container. So when using remove_if (), the actual operation of the data in the container is above. Consider the above example:
1, szremove = "O".
2, vs See the display in the chart below.
Looking at this result, we can see that remove_if () actually modifies the iteration address based on the condition, with some residual data behind it, and data that needs to be deleted. The rest of the data may not be in the original data, but they don't know it.
Call Erase () to delete the remaining data. Note that the result of remove_if () and the Vs.enc () range of data are deleted by erase () in the above example.
Compression of a bloated vector
Many times the amount of data being deleted, or by using the reserve (), results in a vector with much more space than is actually needed. All need to compress the vector to its actual size. Resize () can increase the size of the vector. Clear () can only change the size of the cache, all of which are important for vector free memory nine. How to solve these problems, let us operate.
We can create another vector from a vector. Let's see what's going to happen. Assuming we already have a vector V, its memory size is 1000, and when we call size (), it's only 7. We've wasted a lot of memory. Let's build a vector on it.
Std::vector<cstring> vnew (v);
cout << vnew.capacity ();
Vnew.capacity () returns 7. This means that the newly created space is only allocated according to the actual size. Now we don't want to release V because we're going to use it somewhere else, can we swap V and vnew with swap?
Vnew.swap (v);
cout << vnew.capacity ();
cout << v.capacity ();
Interestingly: Vnew.capacity () is 1000, and v.capacity () is 7.
Now it's up to me, but it's not a very good solution, and we can write this as follows:
Std::vector<cstring> (v). Swap (v);
Can you see what we've done? We created a temporary variable instead of the named one, and then we used swap () so we removed the unnecessary space and got the actual size v.
Conclusion
I hope this document will give valuable references to developers who use the STL vector container. I also hope that by reading this article you can safely use vector to replace the data in the C language.