vector基本概念
定义
C++的vector容器是一个动态数组,提供了存储和操作元素的功能。它是标准模板库(STL)的一部分,在头文件中定义。
vector数据结构和数组非常相似,也称为单端数组(动态数组)(也被称为向量)
使用vector容器前,需要引入头文件:
#include <vector>
vector容器的迭代器——支持随机访问的迭代器
vector与普通数组区别
大小的灵活性
数组是静态空间,而vector可以动态扩展普通数组在创建时需要指定固定的大小,而且不能动态改变大小。而vector容器是动态数组,可以根据需要自动调整大小。它会自动管理内存,并提供了函数来添加、删除、插入和操作元素。
内存管理
普通数组是在栈上分配内存,而vector容器使用堆内存。这意味着当数组很大时,使用vector可以避免栈溢出问题。另外,vector还提供了自动释放内存的机制,不需要手动释放内存。
访问效率
普通数组的元素访问效率更高,因为它们在内存中是连续存储的,可以直接通过索引来访问元素。而vector容器的元素存储在堆内存中,需要通过指针进行间接访问,可能会稍微降低一些效率。
功能和灵活性
vector容器提供了许多便捷的函数和操作符,使得处理和操作元素更加方便。它可以动态调整大小、插入和删除元素,提供了范围-based for循环和迭代器等功能,而普通数组需要手动编写相应的代码来实现这些功能。
综上所述,vector容器相比普通数组更加灵活和方便,尤其适用于需要动态改变大小或者进行复杂操作的场景。而普通数组则更适合在大小固定且访问效率要求较高的情况下使用。
动态扩展
并不是在原空间之后续接新空间,而是找更大的内存空间,然后将原数据拷贝新空间,释放原空间
vector容器在初始化时没有固定的大小限制,可以动态地添加或删除元素,以适应不同的需求。添加元素时,如果已经达到容器的容量上限,vector会自动分配更大的内存空间,并将原有的元素拷贝到新的内存中。这样就实现了动态扩展。
vector构造函数——创建vector容器
函数原型
vector<T> v;
//采用模板实现类实现,默认构造函数vector(v.begin(), v.end());
//将v[begin(), end())区间中的元素拷贝给本身。vector(n, elem);
//构造函数将n个elem拷贝给本身。vector(const vector &vec);
//拷贝构造函数。
示例
#include <iostream>
#include <vector>
int main() {
// 使用默认构造函数创建空的vector容器
std::vector<int> emptyVector;
// 使用迭代器范围方式创建vector容器
int arr[] = {1, 2, 3, 4, 5};
std::vector<int> rangeVector(arr, arr + 5);
// 使用重复元素方式创建vector容器
std::vector<int> repeatVector(5, 10);
// 使用拷贝构造函数创建vector容器
std::vector<int> copyVector(rangeVector);
// 打印各个vector容器的元素
for (int element : emptyVector) {
std::cout << element << " ";
}
std::cout << std::endl;
for (int element : rangeVector) {
std::cout << element << " ";
}
std::cout << std::endl;
for (int element : repeatVector) {
std::cout << element << " ";
}
std::cout << std::endl;
for (int element : copyVector) {
std::cout << element << " ";
}
std::cout << std::endl;
return 0;
}
在上述示例中,我们通过不同的方式创建了四个vector容器:使用默认构造函数创建了一个空的容器emptyVector,使用迭代器范围方式从数组中拷贝元素创建了容器rangeVector,使用重复元素方式创建了容器repeatVector,使用拷贝构造函数从另一个容器中拷贝元素创建了容器copyVector。然后,我们分别使用for循环打印四个vector容器的元素。
注意,在示例代码中,emptyVector是空的,因此不会输出任何内容。
运行该示例代码,输出为:
1 2 3 4 5
10 10 10 10 10
1 2 3 4 5
vector赋值操作
函数原型
-
vector& operator=(const vector &vec);
//重载等号操作符 assign(beg, end);
//将[beg, end)区间中的数据拷贝赋值给本身。assign(n, elem);
//将n个elem拷贝赋值给本身。
注意
beg
和end
都是迭代器
示例
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec1 = {1, 2, 3, 4, 5};
std::vector<int> vec2;
// 使用重载等号操作符将vec1的元素赋值给vec2
vec2 = vec1;
// 使用assign函数将vec1的元素拷贝赋值给vec2
vec2.assign(vec1.begin(), vec1.end());
// 使用assign函数将重复的元素拷贝赋值给vec2
vec2.assign(5, 10);
// 打印vec1和vec2的元素
for (int element : vec1) {
std::cout << element << " ";
}
std::cout << std::endl;
for (int element : vec2) {
std::cout << element << " ";
}
std::cout << std::endl;
return 0;
}
对vector容器的容量和大小操作
函数原型
-
empty();
//判断容器是否为空 -
capacity();
//容器的容量 -
size();
//返回容器中元素的个数 -
resize(int num);
//重新指定容器的长度为num,若容器变长,则以默认值填充新位置。 //如果容器变短,则末尾超出容器长度的元素被删除。
-
resize(int num, elem);
//重新指定容器的长度为num,若容器变长,则以elem值填充新位置。 //如果容器变短,则末尾超出容器长度的元素被删除
示例
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec = {1, 2, 3};
// 使用empty()函数判断容器是否为空
if (vec.empty()) {
std::cout << "Vector is empty" << std::endl;
} else {
std::cout << "Vector is not empty" << std::endl;
}
// 使用capacity()函数获取容器的容量
std::cout << "Capacity: " << vec.capacity() << std::endl;
// 使用size()函数获取容器中元素的个数
std::cout << "Size: " << vec.size() << std::endl;
// 使用resize()函数修改容器的长度为5,默认使用0填充新位置
vec.resize(5);
// 输出修改后的容器元素
for (int element : vec) {
std::cout << element << " ";
}
std::cout << std::endl;
// 使用resize()函数将容器的长度修改为3,并使用10填充新位置
vec.resize(3, 10);
// 输出修改后的容器元素
for (int element : vec) {
std::cout << element << " ";
}
std::cout << std::endl;
return 0;
}
在上述示例中,我们创建了一个初始容器vec,包含元素1、2和3。首先,使用empty()函数判断容器是否为空,如果为空则输出相应的提示信息。然后,使用capacity()函数获取容器的容量,并使用size()函数获取容器中元素的个数。接下来,使用resize()函数将容器的长度修改为5,默认使用0填充新位置。打印修改后的容器元素。接着,使用resize()函数将容器的长度修改为3,并使用10填充新位置。再次打印修改后的容器元素。
输出结果
Vector is not empty
Capacity: 3
Size: 3
1 2 3 0 0
1 2 3
对vector容器进行插入、删除操作
函数原型
push_back(ele);
//尾部插入元素elepop_back();
//删除最后一个元素insert(const_iterator pos, ele);
//迭代器指向位置pos插入元素eleinsert(const_iterator pos, int count,ele);
//迭代器指向位置pos插入count个元素eleerase(const_iterator pos);
//删除迭代器指向的元素erase(const_iterator start, const_iterator end);
//删除迭代器从start到end之间的元素clear();
//删除容器中所有元素
示例
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec = {1, 2, 3};
// 尾部插入元素ele
vec.push_back(4);
// 删除最后一个元素
vec.pop_back();
// 迭代器指向位置pos插入元素ele
auto it = vec.begin() + 1;
vec.insert(it, 10);
// 迭代器指向位置pos插入count个元素ele
vec.insert(it, 3, 20);
// 删除迭代器指向的元素
vec.erase(vec.begin() + 2);
// 删除迭代器从start到end之间的元素
vec.erase(vec.begin(), vec.begin() + 2);
// 删除容器中所有元素
vec.clear();
// 输出修改后的容器元素
for (int element : vec) {
std::cout << element << " ";
}
std::cout << std::endl;
return 0;
}
对vector中的数据的存取操作
函数原型
-
at(int idx);
//返回索引idx所指的数据 -
operator[];
//返回索引idx所指的数据 -
front();
//返回容器中第一个数据元素 -
back();
//返回容器中最后一个数据元素
示例
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
// 使用 at() 函数返回索引 idx 所指的数据
int value1 = vec.at(2);
std::cout << "Value at index 2: " << value1 << std::endl;
// 使用 operator[] 返回索引 idx 所指的数据
int value2 = vec[3];
std::cout << "Value at index 3: " << value2 << std::endl;
// 使用 front() 函数返回容器中第一个数据元素
int first = vec.front();
std::cout << "First element: " << first << std::endl;
// 使用 back() 函数返回容器中最后一个数据元素
int last = vec.back();
std::cout << "Last element: " << last << std::endl;
return 0;
}
在上述示例中,我们创建了一个初始容器 vec,包含元素 1、2、3、4 和 5。然后,我们使用 at() 函数和索引 2 来访问容器中的元素。同样地,我们使用 operator[] 和索引 3 来访问容器中的元素。接下来,我们使用 front() 函数来访问容器中的第一个元素,并使用 back() 函数来访问容器中的最后一个元素。
输出结果
Value at index 2: 3
Value at index 3: 4
First element: 1
Last element: 5
使用迭代器存取数据
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
// 使用迭代器访问容器中的数据
std::vector<int>::iterator it;
// 使用迭代器遍历容器并输出数据
std::cout << "Elements in the vector: ";
for (it = vec.begin(); it != vec.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
return 0;
}
在上述示例中,我们创建了一个初始容器 vec,包含元素 1、2、3、4 和 5。
然后,我们声明了一个迭代器 it,并将其初始化为容器的起始位置(begin())。
接下来,我们使用迭代器 it 遍历容器,并通过解引用操作符*
访问迭代器指向的元素。
在循环中,迭代器 it逐个移动到下一个元素,直到达到容器的末尾位置(end())为止。
在循环过程中,我们输出迭代器指向的元素值。最后,我们输出一个换行符。
实现两个vector容器内元素进行互换
函数原型
swap(vec);
// 将vec与本身的元素互换
示例
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
std::cout << "Before swap:" << std::endl;
for (const auto& value : vec) {
std::cout << value << " ";
}
std::cout << std::endl;
swap(vec); // 使用 std::swap 交换 vec 与本身的元素
std::cout << "After swap:" << std::endl;
for (const auto& value : vec) {
std::cout << value << " ";
}
std::cout << std::endl;
return 0;
}
在上述示例中,我们创建了一个初始容器 vec,包含元素 1、2、3、4 和 5。
然后,我们输出容器交换前的元素值。
接下来,我们调用 swap(vec),使用 std::swap 函数交换容器 vec 与其本身的元素,实现元素的重新排列。
最后,我们输出容器交换后的元素值
输出结果
Before swap:
1 2 3 4 5
After swap:
5 4 3 2 1
vector预留空间
可以减少vector在动态扩展容量时的扩展次数
函数原型
reserve(int len);
//容器预留len个元素长度,预留位置不初始化,元素不可访问。
在调用 reserve()
函数时,需要提供一个整数值作为参数,表示预分配的最小容量。这个容量是指可以容纳的元素数量,并不是占用的字节大小
示例
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec;
std::cout << "Capacity before reserve: " << vec.capacity() << std::endl;
vec.reserve(10); // 预留至少能容纳10个元素的空间
std::cout << "Capacity after reserve: " << vec.capacity() << std::endl;
return 0;
}
我们创建了一个空的 std::vector 容器 vec。
然后,我们输出容器调用 reserve() 函数之前的容量。
接下来,我们调用 vec.reserve(10),预留至少能容纳 10 个元素的空间。
最后,我们输出容器调用 reserve() 函数之后的容量。
输出
Capacity before reserve: 0
Capacity after reserve: 10
注意——如果数据量较大,可以一开始利用reserve预留空间
如果事先知道容器将要存储大量的元素,那么通过使用 reserve() 函数来预留空间是一个很好的做法。这样可以避免在插入元素时多次重新分配内存,从而提高性能。文章来源:https://www.toymoban.com/news/detail-634939.html
预留足够的空间以容纳数据可以减少频繁的重新分配和复制操作,从而提高程序的效率。特别是对于大型数据集或需要频繁插入或添加元素的情况,这一点尤为重要。文章来源地址https://www.toymoban.com/news/detail-634939.html
到了这里,关于Day 23 C++ vector容器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!