C++ vector basic operations

Table of contents

1. Introduction

2. Definition

3. Iterator

4. Capacity operation

1、size

2、capacity

3、empty

4、resize

5、reserve

Summary (expansion mechanism)

5. Add, delete, check and modify

1、push_back & pop_back

2、find

3、insert

4、erase

5、swap

6、operator[]


1. Introduction

Document introduction to vector

  1. A vector is a sequence container that represents a variable-sized array.
  2. Just 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.
  3. Essentially, vector uses a dynamically allocated array to store its elements. When new elements are inserted, the array needs to be resized to increase storage space. This is done by allocating a new array and then moving all elements into this array. In terms of time, this is a relatively expensive task, because the vector is not resized every time a new element is added to the container.
  4. Vector allocation space strategy: vector allocates some extra space to accommodate possible growth because the storage space is larger than the actual storage space required. Different libraries use different strategies to trade off space usage and reallocation. But in any case, the reallocation should be logarithmically increasing in interval size, so that inserting an element at the end is done in constant time.
  5. Therefore, vector takes up more storage space in order to gain the ability to manage storage space and grow dynamically in an efficient manner.
  6. Compared with other dynamic sequence containers (deque, list and forward_list), vector is more efficient when accessing elements, and adding and deleting elements at the end is relatively efficient. For other deletion and insertion operations that are not at the end, the efficiency is even lower. It is better to use unified iterators and references than list and forward_list.

Use of vector

When learning vector, you must learn to check the documentation:Vector’s documentation, vector is very important in practice, and we are familiar with it in practice Common interfaces will do.

Second,Defined

These are the different overloaded forms of the constructor of the `vector` class in the C++ standard library. Below is an explanation of each constructor:

1. Parameterless constructor: `vector()` 

vector<int> v;
  • Creates an empty `vector` object containing no elements.

2. Construct and initialize n vals: `vector(size_type n, const value_type& val = value_type())`

vector<int> v1(10, 1);
  • Create a `vector` object containing `n` elements, each element initialized to `val`.
  • An initial value `val` can optionally be provided, if not provided the default constructor of the default value type is used for initialization.

3. Use iterator for initialization construction: `vector(InputIterator first, InputIterator last)`

string s1("hello");
vector<char> v3(s1.begin(), s1.end());
  • Create a `vector` object and initialize it with elements in the range `[first, last)`.
  • `first` and `last` are iterators specifying the range of elements to be copied.
  • This constructor allows the use of an iterator to specify a range of elements to copy, which can be an array, container, or other iterable object.

4. Copy constructor: `vector(const vector& x)` Key points

vector<int>v1(v);
  • Creates a new `vector` object whose elements are the same as another `vector` object `x`.
  • The copy constructor is used to create a copy. The new `vector` object will be independent of the original object, and modifications to one object will not affect the other object.

Let's take an example to demonstrate. The output is the same as the string class, with three methods: range for [] iterator.

void test1()
{
	//无参构造
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);

	//三种输出方式 范围for [] 迭代器
	for (auto a : v)
	{
		cout << a << " ";
	}
	cout << endl;

	for (size_t i = 0; i < v.size(); i++)
	{
		cout << v[i] << " ";
	}
	cout << endl;

	//vector<int>::iterator it = v.begin();
	auto it = v.begin();
	while (it != v.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
	
	//拷贝构造
	vector<int> copy(v);
	for (auto a : copy) 
	{
		cout << a << " ";
	}
	cout << endl;
}
void test2()
{
	//构造并初始化
	vector<int> v1(6, 6);
	for (auto a : v1)
	{
		cout << a << " ";
	}
	cout << endl;

	//迭代器
	vector<int> v2(v1.begin(), v1.end());
	for (auto b : v2)
	{
		cout << b << " ";
	}
	cout << endl;

	string s1("hello");
	vector<char> v3(s1.begin(), s1.end());
	for (auto b : v3)
	{
		cout << b << " ";
	}

}
int main()
{
	test1();
    cout << endl;
    test2();
	return 0;
}

3. Iterator

begin()/end(): Get the iterator/const_iterator of the first data position, get the iterator/const_iterator of the next position of the last data

rbegin()/rend():Get the reverse_iterator of the last data position, and get the reverse_iterator of the previous position of the first data

By using these interfaces, iterative operations can be performed invector.

  • For example, using begin() and end() can traverse the elements in vector, while using rbegin() and rend() can traverse the elements in vector in reverse.
  • Please note that for read-onlyvector, const_iterator and const_reverse_iterator should be used to ensure no modificationElements of vector.
void test3()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
    //正向迭代器
	vector<int>::iterator it = v.begin();
	while (it != v.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
    //反向迭代器
	vector<int>::reverse_iterator rit = v.rbegin();
	while (rit != v.rend())
	{
		cout << *rit << " ";
		++rit;
	}
}
int main()
{
    test3();
    return 0;
}

4. Capacity operation

1、size

Get the number of data.
int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};
    std::cout << "Size of vector: " << v.size() << std::endl;
    return 0;
}

2、capacity

capacityGet the capacity size.
int main() {
    std::vector<int> v;
    std::cout << "Initial capacity: " << v.capacity() << std::endl;
    for (int i = 0; i < 10; i++) {
        v.push_back(i);
        std::cout << "Capacity after pushing " << i << ": " << v.capacity() << std::endl;
    }
    return 0;
}

3、empty

Determine whether it is empty.
int main() {
    std::vector<int> v;
    std::cout << "Is vector empty? " << (v.empty() ? "Yes" : "No") << std::endl;
    v.push_back(1);
    std::cout << "Is vector empty? " << (v.empty() ? "Yes" : "No") << std::endl;
    return 0;
}

4、resize

Change the size of vector.
void resize (size_type n, value_type val = value_type());
  1. Resize the container so that it contains n elements.
  2. If n is smaller than the current containersize, the content will be reduced to its first n a> elements, remove excess elements (and destroy them).
  3. If n is larger than the current containersize, extend the content by inserting any number of elements at the end to reach < The size of a i=3>n . If val is specified, the new element will be initialized to a copy of val , otherwise they will initialize the value.
  4. If n is also larger than the current container capacity, then The allocated storage space is automatically reallocated.
  5. Note that this function changes the actual contents of the container by inserting or erasing elements from the container.
int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};
    v.resize(7, 100);
    for (int i : v) {
        std::cout << i << " ";
    }
    std::cout << std::endl;
    v.resize(3);
    for (int i : v) {
        std::cout << i << " ";
    }
    return 0;
}

5、reserve

Change the capacity of vector.
reserve(): This method changes the capacity of vector. If the new capacity is larger than the current capacity, the vector's memory will be reallocated to accommodate the additional elements. If the new capacity is smaller than the current capacity, this method will have no effect.
int main() {
    std::vector<int> v;
    std::cout << "Initial capacity: " << v.capacity() << std::endl;
    v.reserve(10);
    std::cout << "Capacity after reserving: " << v.capacity() << std::endl;
    return 0;
}

Summary (expansion mechanism)

  • If you run the capacity code under VS and g++ respectively, you will find that capacity increases by 1.5 times under VS and 2 times by g++.
  • This issue is often investigated. Don’t rigidly believe that the vector capacity is increased by 2 times. The specific increase is defined based on 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 for sure how much space is needed, reserve can alleviate the cost problem of vector expansion.
  • Resize will also initialize while opening space, which affects size.

The default expansion mechanism of vector can be observed through the following code.

void TestVectorExpand()
{
	size_t sz;
	vector<int> v;
	sz = v.capacity();
	cout << "making v grow:\n";
	for (int i = 0; i < 100; ++i)
	{
		v.push_back(i);
		if (sz != v.capacity())
		{
			sz = v.capacity();
			cout << "capacity changed: " << sz << '\n';
		}
	}
}

If you have determined the approximate number of elements to be stored in the vector, you can set enough space in advance to avoid the problem of inefficiency caused by expansion while inserting.

void TestVectorExpandOP()
{
	vector<int> v;
	size_t sz = v.capacity();
	v.reserve(100); // 提前将容量设置好,可以避免一遍插入一遍扩容
	cout << "making bar grow:\n";
	for (int i = 0; i < 100; ++i)
	{
		v.push_back(i);
		if (sz != v.capacity())
		{
			sz = v.capacity();
			cout << "capacity changed: " << sz << '\n';
		}
	}
}

5. Add, delete, check and modify

1、push_back & pop_back

End insertion & end deletion
int main() {
	std::vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	for (int i : v) {
		std::cout << i << " ";
	}
	cout << endl;
	v.pop_back();
	for (int i : v) {
		std::cout << i << " ";
	}
	return 0;
}

2、find

  • Find The find function is a function in the algorithm module, used to find specific elements in a vector.
  • It takes the start and end positions of the element to be found and returns an iterator pointing to that element.
  • For example, if you have a vector v, you can use std::find(v.begin(), v.end(), 5) to find the integer 5 in v.

3、insert

  • Insertion The insert function is used to insert an element before the specified position. It requires providing the position to insert and the value to insert as parameters.
  • For example, if you have a vector v, you can use v.insert(v.begin() + 2, 10) to insert the integer 10 at the third position of v.

4、erase

  • Delete The erase function is used to delete the element at the specified position. It takes the position to be deleted as a parameter and returns an iterator pointing to the position after the deleted element.
  • For example, if you have a vector v, you can use v.erase(v.begin() + 3) to delete the fourth element of v.

The following code demonstrates an example of inserting, searching, and deleting operations on a vector.

void test5()
{
    vector<int> v;
    v.push_back(1); // 在vector末尾插入元素1
    v.push_back(2); // 在vector末尾插入元素2
    v.push_back(3); // 在vector末尾插入元素3
    v.push_back(4); // 在vector末尾插入元素4

    for (auto e : v)
    {
        cout << e << " "; // 输出vector中的每个元素
    }
    cout << endl;
    // 在vector中查找值为2的元素
    vector<int>::iterator pos = find(v.begin(), v.end(), 2); 
    if (pos != v.end())
    {
        v.insert(pos, 20); // 在找到的位置之前插入元素20
    }

    for (auto e : v)
    {
        cout << e << " "; // 输出修改后的vector中的每个元素
    }
    cout << endl;

    pos = find(v.begin(), v.end(), 2); // 再次查找值为2的元素
    if (pos != v.end())
    {
        v.erase(pos); // 删除找到的元素
    }

    for (auto e : v)
    {
        cout << e << " "; // 输出修改后的vector中的每个元素
    }
    cout << endl;

    v.erase(v.begin()); // 删除vector的第一个元素

    for (auto e : v)
    {
        cout << e << " "; // 输出修改后的vector中的每个元素
    }
    cout << endl;
}

int main()
{
    test5();
    return 0;
}

5、swap

  • Swap The swap function is used to swap the data spaces of two vectors. It needs to provide another vector as a parameter and exchange the contents of the current vector with the contents of the parameter vector.
  • For example, if you have two vectors v1 and v2, you can use v1.swap(v2) to swap their contents.
int main() {
	std::vector<int> v1 = { 1, 2, 3 };
	std::vector<int> v2 = { 4, 5, 6 };
	v1.swap(v2);
	for (int i : v1) {
		cout << i << " ";
	}
	cout << endl;
	for (int i : v2) {
		cout << i << " ";
	}
	return 0;
}

6、operator[]

access like array

int main()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);

	for (size_t i = 0; i < v.size(); ++i)
	{
		cout << v[i] << " ";
	}

	return 0;
}

Guess you like

Origin blog.csdn.net/m0_73800602/article/details/134853098