Table of contents
Introduction to vector
- A vector is a sequence container of variable-sized arrays.
- Like arrays, vectors also use continuous storage space to store elements. This means that you can use subscripts to access the elements of the vector, which is as efficient as an array. But unlike an array, its size can be changed dynamically, and its size will be automatically handled by the container.
Think about a question: Can it be
vector<char>
replacedstring
?
The answer is no: there are two reasons:
1. The structure is different, and the string requirement is the last'\0'
. In order to be better compatible with C, the functions of string will be'\0'
processed, but the functions of vector will not.
2. There are many unique interface functions in string.
Use of vector
Definition of vector
template < class T, class Alloc = allocator<T> > class vector;
The definition of vector is in the form of a template, because there are different types of templates
. There are two template parameters,
class T
which refer to the type of the element. There are aliases in the class , because the space configurator (memory pool) is value_type
carried out in the class. typedef T value_type
class Alloc = allocator<T>
Default value, usually we do not need to pass this parameter
vector interface function
Constructor and assignment overloading
Constructor | illustrate |
---|---|
vector() | No-argument construction |
vector(size_type n,const value_type& val = value_type()) | Construct and initialize n vals |
vector (const vector& x); | copy construction |
vector (InputIterator first, InputIterator last); | Initialization using iterators |
vector()
We don’t need to say more about the parameterless structure.
vector(size_type n,const value_type& val = value_type())
, value_type
that is T
, the default value typedef
that comes out is actually the constructor of the element type in the container, and the value constructed with no parameters is the default value.
val
value_type()
If the type of T here is a custom type
Date
, then the default valueDate()
is the default constructor. We can all understand that
if the type of T is a built-in type, for exampleint
,int()
what does it mean?
This is actually an optimization in C++, int() will actually be 0
void test1()
{
vector<int> v(5, 2); //22222
}
vector (const vector& x);
There’s not much to say about copy construction.
vector (InputIterator first, InputIterator last);
, the iterator here can be of its own container, other containers, or even an array.
void test1()
{
vector<int> v1(5, 98);
vector<int> v2(v1.begin(), v1.end());//相同类型的迭代器
for (auto e : v2)
{
cout << e << " ";
e++;
}//输出98 98 98 98 98
cout << endl;
vector<char> v3(v1.begin(), v1.end());//相同容器不同元素类型的迭代器
for (auto e : v3)
{
cout << e << " ";
e++;
}//输出b b b b b
cout << endl;
int nums[] = {
1,2,3,4,5,6 };
vector<int> v4(nums, nums + sizeof(nums) / sizeof(int));//数组
for (auto e : v4)
{
cout << e << " ";
e++;
}//输出1 2 3 4 5 6
cout << endl;
}
Assignment overloading
vector& operator= (const vector& x);
void test2()
{
vector<char> v1(10, 'x');
vector<char> v2;
v1 = v2;//xxxxxxxxxx
}
Iterator
The iterator here is also a pointer.
The usage is similar to the previous string iterator.
void test2()
{
int nums[] = {
1,2,3,4,5,6,7,8,9,10 };
vector<int> v(nums, nums + 10);
vector<int>::iterator it = v.begin();
while (it != v.end())
{
cout << *it << " ";
it++;
}//1 2 3 4 5 6 7 8 9 10
cout << endl;
vector<int>::reverse_iterator rit = v.rbegin();
while (rit != v.rend())
{
cout << *rit << " ";
rit++;
}//10 9 8 7 6 5 4 3 2 1
cout << endl;
const vector<int> cv(nums, nums + 10);
vector<int>::const_iterator cit = cv.cbegin();
while (cit != cv.cend())
{
cout << *cit << " ";
cit++;
}//1 2 3 4 5 6 7 8 9 10
cout << endl;
vector<int>::const_reverse_iterator crit = cv.crbegin();
while (crit != cv.crend())
{
cout << *crit << " ";
crit++;
}//10 9 8 7 6 5 4 3 2 1
cout << endl;
}
element access
vector
[] is also overloaded in operator []
reference operator[] (size_type n);//读写
const_reference operator[] (size_type n) const;//只读
The usage is the same as string::operator[].
It will still assert to determine whether the subscript is out of bounds.
at
reference at (size_type n);
const_reference at (size_type n) const;
Usage and at
Similarity
If the subscript is out of bounds, an exception will be thrown.
front and back
front
Return the first element
back
and return the last element.
These two functions are not commonly used and can be []
replaced by: v.front()–>v[0] v.back()–>v[v.size()-1]
data
value_type* data() noexcept;
const value_type* data() const noexcept;
Returns a direct pointer to a memory array
vector capacity related function
function | illustrate |
---|---|
size | Get the number of data |
max_size | Get the maximum number of data |
capacity | Get capacity size |
empty | Call it short |
shrink_to_fit | Reduce to fit capacity |
resize | Adjust size |
reserve | Adjust capacity |
These functions are also available in string, and their usage is similar.
There are only reserve
slight differences between functions and strings.
If n is greater than the current vector capacity, the function will cause the container to reallocate storage space and increase the capacity to n (or greater).
In all other cases, the function call does not cause a reallocation, and the vector capacity is not affected.
This is different from the reserve in string. If n<capacity(), the reserve in string may be reduced, depending on the compiler,
but n<capacity() in vector will not reduce capacity.
When the capacity code is run under vs and g++ respectively, it will be found that the capacity under vs increases by 1.5 times, and g++ increases by 2 times.
But don't solidify that the specific growth rate is defined according to specific needs. vs is the PJ version STL, g++ is the SGI version STL.
Reserve is only responsible for opening up space. If you know how much space is needed, reserve can alleviate the cost defect of vector capacity expansion.
resize affects size() and capacity()
There is a situation below. We first construct a vector<int>
type object with no parameters, and then use the reserve function to open up space. What will happen if we []
use it to assign a value?
void test3()
{
vector<int> v;
v.reserve(20);
v[0] = 1;
v[1] = 2;
}
The answer is that the program will report an error.
The reason is that although reserve(20) is used to open up 20 spaces, it size()
is 0 at this time
and then we assign []
the value through it. operator[]
There is an assertion inside the function assert
, and an error will be reported here.
So like the situation above, you need to use resize
functions, resize
which can be changed size
or changedcapacity
void test3()
{
vector<int> v;
v.resize(20);
v[0] = 1;
v[1] = 2;
}
Add deletion and modification operations to vector
push_back
void push_back (const value_type& val);
Function: insert an element at the end
pop_back
void pop_back();
Function: delete the last element
insert
iterator insert (iterator position, const value_type& val);
void insert (iterator position, size_type n, const value_type& val);
template <class InputIterator>
void insert (iterator position, InputIterator first, InputIterator last);
The insert function of the previous string type is inserted at the pos position of the size_t type,
while the insert in the vector is inserted at the position of the iterator
iterator insert (iterator position, const value_type& val)
, insert at the position iterator positionval
void insert (iterator position, size_type n, const value_type& val)
n
, insert an item at the position iterator positionval
template <class InputIterator> void insert (iterator position, InputIterator first, InputIterator last);
Insert the contents of [frist, last) iterator range at the position of the iterator
void test4()
{
vector<int> v;
v.push_back(0);
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
v.push_back(6);
v.push_back(7);
v.insert(v.begin() + 3,100);//0 1 2 (100) 3 4 5 6 7
v.insert(v.begin(), 2, 10);//(10 10) 0 1 2 100 3 4 5 6 7
int num[] = {
12,13,14,15 };
v.insert(v.begin() + 1, num, num + 4);//10 (12 13 14 15) 10 0 1 2 100 3 4 5 6 7
for (auto e : v)
{
cout << e<<" ";
e++;
}
}
erase
iterator erase (iterator position);
iterator erase (iterator first, iterator last);
iterator erase (iterator position)
Delete the element at the position of the iterator
iterator erase (iterator first, iterator last)
Delete the content in the [first, last) iterator range
void test5()
{
vector<int> v;
v.push_back(0);
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
v.push_back(6);
v.push_back(7);
//0 1 2 3 4 5 6 7
v.erase(v.begin()); //1 2 3 4 5 6 7
v.erase(v.begin() + 2, v.end());//1 2
}
The above
erase
suminsert
will involve iterator failure, which we will understand later
swap
void swap (vector& x);
Swap the data spaces of two vectors
clear
void clear();
Clear the content
Make the value of size() become 0 without changing the value of capacity()
Relational operators
The overloading of various relational operators is also supported in vector, and these functions are overloaded for non-member functions
Relational operators are very useful for strings, but relational operators are not very useful for vectors