STLDay1

Uncategorized
6.7k words

std::vector

简介:是一个动态数组,提供高效的随机访问和动态扩容功能。
(内部使用连续的内存块存储元素,通过索引快速访问元素的时间复杂度为O(1))
(会自动管理内存,当元素数量超过当前容量时,会自动分配更大的内存块并复制元素)
(支持迭代器,可方便地遍历容器中的元素)
(泛型编程,是一个模板类,可存储任意类型的元素,如int ,double, std::string 等)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <vector>

int main() {
// 初始化
std::vector<int> vec = {1, 2, 3};

// 添加元素
vec.push_back(4);
vec.insert(vec.begin() + 2, 10);

// 删除元素
vec.pop_back(); //删除尾部元素
vec.erase(vec.begin() + 1); //删除第二个元素

// 访问元素
std::cout << "First element: " << vec.front() << std::endl;
std::cout << "Last element: " << vec.back() << std::endl;

// 获取大小和容量
std::cout << "Size: " << vec.size() << std::endl;
std::cout << "Capacity: " << vec.capacity() << std::endl;

// 遍历元素
std::cout << "Elements: ";
for (int i : vec) {
std::cout << i << " ";
}
std::cout << std::endl;

return 0;
}

范围-based for 循环

1
2
3
for (元素类型 变量名 : 容器) {
// 使用变量名访问元素
}

注:

  • 范围-based for 循环不仅适用于 std::vector,还适用于其他 STL 容器(如 std::list、std::map 等)以及数组。
  • 代码块的结束必须在新的一行使用三个反引号,而且前后不能有多余的空格或其他字符,只需要简单地写 ‘ ``` ’。
  • 默认情况下,范围-based for 循环是只读的。如果需要修改容器中的元素,需要使用引用:
1
2
3
for (int& i : vec) {
i *= 2; // 修改元素
}

vector.front() & vector.back()

(成员函数)返回第一个 / 最后一个元素的引用,使你能够访问和修改它。

语法:

1
2
reference front(); // reference back();
const_reference front() const; // const_reference back() const;
  • 返回类型
    • 如果 vec 是非 const 容器,front() 返回对第一个元素的 引用,类型为 reference
    • 如果 vecconst 容器,front() 返回对第一个元素的 常量引用,类型为 const_reference
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <vector>

int main() {
std::vector<int> vec = {10, 20, 30, 40, 50};

// 访问第一个元素
std::cout << "The first element is: " << vec.front() << std::endl; // 输出: 10

// 修改第一个元素
vec.front() = 100;
std::cout << "After modification, the first element is: " << vec.front() << std::endl; // 输出: 100
return 0;
}

back()同理

vector.push_back()

(成员函数)将一个元素添加到容器末尾

语法:

1
2
void push_back(const T& value);
void push_back(T&& value);
  • push_back(const T& value):将一个值为 value 的元素添加到 std::vector 的末尾。value 是一个常量引用,可以是 std::vector 中存储的类型的任何对象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//添加单个元素
#include <iostream>
#include <vector>

int main() {
std::vector<int> vec = {1, 2, 3}; // 初始包含三个元素

// 添加一个元素 4 到 vec 的末尾
vec.push_back(4);

// 输出修改后的 vec
for (int i : vec) {
std::cout << i << " "; // 输出: 1 2 3 4
}
std::cout << std::endl;

return 0;
}
  • push_back(T&& value):通过右值引用将一个临时对象(或可移动对象)添加到容器末尾,这样可以避免不必要的拷贝,提高效率
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//使用右值引用优化
#include <iostream>
#include <vector>

int main() {
std::vector<int> vec;

// 使用右值引用插入临时对象
vec.push_back(10); // 这里的 10 是一个临时对象

// 输出修改后的 vec
for (int i : vec) {
std::cout << i << " "; // 输出: 10
}
std::cout << std::endl;

return 0;
}
//在这个例子中,10 是一个右值,调用 push_back 时,使用的是右值引用,因此元素 10 被直接移动到容器末尾,避免了不必要的拷贝。

vector.pop_back()

(成员函数)用于删除末尾元素

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec = {1, 2, 3, 4};
// 删除末尾的元素
vec.pop_back();
// 输出修改后的 vec
for (int i : vec) {
std::cout << i << " "; // 输出: 1 2 3
}
std::cout << std::endl;
return 0;
}

访问内部元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <vector>

#include <iterator> // 仅std::next()需要用到

int main() {
std::vector<int> vec = {10, 20, 30, 40, 50};

// 使用下标索引访问
std::cout << "Element at index 2: " << vec[2] << std::endl; // 输出: 30

// 使用 at() 访问
std::cout << "Element at index 2: " << vec.at(2) << std::endl; // 输出: 30

// 使用迭代器访问
std::vector<int>::iterator it = vec.begin() + 2;
std::cout << "Element at index 2: " << *it << std::endl; // 输出: 30

// 计算中间索引并访问
size_t mid_index = vec.size() / 2;
std::cout << "Middle element: " << vec[mid_index] << std::endl; // 输出: 30(偶数个元素时取中间偏右)

// 使用 std::next 获取中间元素的迭代器
auto it = std::next(vec.begin(), vec.size() / 2);
std::cout << "Middle element: " << *it << std::endl; // 输出: 30

return 0;
}

vector.insert

(成员函数)用于在指定位置插入一个或多个元素,作用是将新元素插入到容器的指定位置,并将原有元素向后移动,以腾出空间。

语法:

1
2
3
4
5
iterator insert(iterator pos, const T& value);//插入单个元素
iterator insert(iterator pos, T&& value);
iterator insert(iterator pos, size_type count, const T& value);//插入多个相同的元素
template <class InputIterator>
iterator insert(iterator pos, InputIterator first, InputIterator last);//插入一个范围的元素

1. insert(iterator pos, const T& value) 插入单个元素

  • 在指定位置 pos 插入单个元素 value
  • pos 是一个指向容器中某个位置的迭代器。
  • 该方法返回一个迭代器,指向新插入的元素。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <vector>

int main() {
std::vector<int> vec = {1, 2, 3, 4};

// 在索引 2 处插入元素 10
auto it = vec.insert(vec.begin() + 2, 10);

// 输出修改后的 vec
for (int i : vec) {
std::cout << i << " "; // 输出: 1 2 10 3 4
}
std::cout << std::endl;

// 输出新插入元素的值
std::cout << "Inserted element: " << *it << std::endl; // 输出: 10

return 0;
}

2. insert(iterator pos, T&& value)

  • 这个版本与第一个类似,但是它允许传递一个右值引用(T&&),适用于插入可以被移动的对象。

3. insert(iterator pos, size_type count, const T& value) 插入多个相同的元素

  • 在指定位置 pos 插入 count 个值为 value 的元素。
  • 如果你希望插入多个相同的元素,可以使用这个版本。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec = {1, 2, 3, 4};

// 在索引 2 处插入 3 个值为 10 的元素
vec.insert(vec.begin() + 2, 3, 10);

// 输出修改后的 vec
for (int i : vec) {
std::cout << i << " "; // 输出: 1 2 10 10 10 3 4
}
std::cout << std::endl;

return 0;
}

4. insert(iterator pos, InputIterator first, InputIterator last) 插入一个范围的元素

  • 在指定位置 pos 插入一个范围 [first, last) 中的所有元素。
  • 这可以用来将一个容器或其他可迭代范围的元素插入到当前容器中

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <vector>

int main() {
std::vector<int> vec = {1, 2, 3, 4};
std::vector<int> new_elements = {5, 6, 7};

// 在索引 2 处插入 new_elements 的所有元素
vec.insert(vec.begin() + 2, new_elements.begin(), new_elements.end());

// 输出修改后的 vec
for (int i : vec) {
std::cout << i << " "; // 输出: 1 2 5 6 7 3 4
}
std::cout << std::endl;

return 0;
}

注:
&vec.begin() 返回一个指向 vec 第一个元素的迭代器。通过 + 2 操作,vec.begin() + 2 将返回一个指向容器中第 3 个元素的迭代器(因为迭代器是从 0 开始的)。换句话说,它指向了容器的第三个位置。
&*it解引用操作符,它用于访问迭代器 it 指向的元素。换句话说,*it 返回 it 所指向位置的值。

注:
返回值:返回迭代器,insert 返回一个迭代器,指向新插入的元素(对于插入单个元素的情况)。如果插入了多个元素,则指向插入区域中的第一个元素。

vec.erase

(成员函数)用于删除容器中一个或多个元素

语法:

1
2
iterator erase(iterator position);
iterator erase(iterator first, iterator last);

1.iterator erase(iterator position)

  • 删除容器中指定位置的单个元素。
  • position 是一个指向要删除元素的迭代器。
  • 返回值是指向删除元素后容器中下一个元素的迭代器。如果删除的是容器的最后一个元素,则返回 vec.end()

2.iterator erase(iterator first, iterator last)

  • 删除容器中从 firstlast 之间的多个元素(first 包含,last 不包含)。
  • firstlast 是迭代器,分别指向要删除元素的起始位置和结束位置。
  • 返回值是指向删除范围之后第一个元素的迭代器。如果删除的是容器的最后一部分,返回 vec.end()

vector.size()&vector.capacity()

(均为成员函数)size返回容器当前包含的元素个数(容器的大小);capacity返回容器能够容纳的元素的总容量(已经分配的内存空间中可以存储的元素数量,不是当前实际的元素数量)

std::vector 是一个动态数组,当元素数量超过当前容量时,它会自动扩容。扩容的过程包括:

  1. 分配一块更大的内存(通常是当前容量的 2 倍)。
  2. 将原有元素复制到新内存中。
  3. 释放旧内存。
Comments