Basic usage of STL vector

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>replaced string?
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 Twhich refer to the type of the element. There are aliases in the class , because the space configurator (memory pool) is value_typecarried 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_typethat is T, the default value typedefthat comes out is actually the constructor of the element type in the container, and the value constructed with no parameters is the default value.
valvalue_type()

If the type of T here is a custom type Date, then the default value Date()is the default constructor. We can all understand that
if the type of T is a built-in type, for example int, 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 atSimilarity
If the subscript is out of bounds, an exception will be thrown.


front and back

frontReturn the first element
backand 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 reserveslight 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.
insert image description here
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 resizefunctions, resizewhich can be changed sizeor 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 erasesum insertwill 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
insert image description here

Relational operators are very useful for strings, but relational operators are not very useful for vectors

Guess you like

Origin blog.csdn.net/weixin_64116522/article/details/132391309