一、vector简介
在 C++ 中,std::vector
是标准库提供的一个容器类,用于存储动态大小的元素序列(即"动态数组")。它提供了一系列成员函数和操作符,使得元素的访问、插入、删除等操作变得方便和高效。
- vector与数组的区别
- 扩展:数组的大小在创建时就确定了,无法动态改变,而
std::vector
空间可以动态扩展(不是在原空间后拼接新空间,而是找更大的内存空间,然后将原数据拷贝到新空间,并释放原空间) - 内存管理:数组在栈上或静态存储区中分配内存,大小是在编译时确定的。而
std::vector
使用动态内存分配,它在堆上分配内存,并自动处理内存的释放。 - 访问和操作:数组使用下标操作符
[]
访问元素,而std::vector
也支持下标操作符,还提供了一些额外的成员函数来方便地操作元素,例如push_back()
、pop_back()
、insert()
、erase()
等。 - 大小管理:数组的大小是固定的,无法改变,而
std::vector
可以动态增长或缩小,可以使用resize()
函数调整大小。 - 内存开销:由于
std::vector
使用动态内存分配,它可能会引入一些额外的开销,例如内存分配和释放的开销。而数组在编译时就分配了固定大小的内存,因此没有这些开销。 - 标准库支持:
std::vector
是 C++ 标准库提供的容器,提供了许多方便的函数和算法来操作和管理元素。而数组是 C++ 的基本数据结构之一,没有提供类似的标准库支持。
总结
- 数组适用于大小固定且事先知道元素数量的情况下使用,尤其是数据集较小或需要静态分配内存的场景。
vector
适用于大小可变的情况,特别是需要动态增长或缩小的场景,并且具有更多的功能和灵活性。
二、vector 构造函数
示例:
#include <iostream>
#include <vector> //必须包含该头文件
using namespace std;
void printVec(vector<int> &v)
{
for (vector<int>::iterator At = v.begin(); At != v.end(); At++)
{
cout << *At << " ";
}
cout << endl;
}
void printVec(vector<double> &v)
{
for (vector<double>::iterator At = v.begin(); At != v.end(); At++)
{
cout << *At << " ";
}
cout << endl;
}
void test01()
{
vector<int> v1;
v1.push_back(10); //添加元素
v1.push_back(20);
printVec(v1);
vector<int> v2(v1.begin(), v1.end());
printVec(v2);
vector<double> v3(5, 6.32);
printVec(v3);
vector<double> v4(v3);
printVec(v4);
}
int main()
{
test01();
system("pause");
return 0;
}
std::vector
作为函数的参数或者返回值时,不能缺少其中的“&”。
三、vector 赋值
示例:
#include <iostream>
#include <vector> //必须包含该头文件
using namespace std;
void printVec(vector<int> &v)
{
for (vector<int>::iterator At = v.begin(); At != v.end(); At++)
{
cout << *At << " ";
}
cout << endl;
}
void test01()
{
vector<int> v1;
v1.push_back(10); //添加元素
v1.push_back(20);
printVec(v1);
vector<int> v2 = v1;
printVec(v2);
vector<int> v3;
v3.assign(v1.begin(), v1.end());
printVec(v3);
vector<int> v4;
v4.assign(6, 1);
printVec(v4);
}
int main()
{
test01();
system("pause");
return 0;
}
四、vector 容量与长度
示例:
#include <iostream>
#include <vector> //必须包含该头文件
using namespace std;
void printVec(vector<int> &v)
{
for (vector<int>::iterator At = v.begin(); At != v.end(); At++)
{
cout << *At << " ";
}
cout << endl;
}
void test01()
{
vector<int> v1;
if(v1.empty()) //判断是否为空
{
cout << "当前v1为空!"<< endl;
}
v1.push_back(10); //添加元素
v1.push_back(20);
v1.push_back(30);
if(! v1.empty())
{
cout << "v1中元素个数:"<< v1.size() << endl;
cout << "v1的容量:"<< v1.capacity() << endl;
printVec(v1);
}
v1.resize(5);
printVec(v1);
v1.resize(10,1);
printVec(v1);
}
int main()
{
test01();
system("pause");
return 0;
}
五、vector 插入与删除
示例:
#include <iostream>
#include <vector> //必须包含该头文件
using namespace std;
void printVec(vector<int> &v)
{
for (vector<int>::iterator At = v.begin(); At != v.end(); At++)
{
cout << *At << " ";
}
cout << endl;
}
void test01()
{
vector<int> v1;
v1.push_back(1); //尾部添加元素
v1.push_back(2);
v1.push_back(3);
v1.push_back(3);
printVec(v1);
v1.pop_back(); //尾部删除元素
printVec(v1);
v1.insert(v1.begin(), 100); //插入元素100
printVec(v1);
v1.insert(v1.begin(), 5, 100); //插入5个元素100
printVec(v1);
v1.erase(v1.begin()); //删除元素
printVec(v1);
v1.clear(); //清空容器
printVec(v1);
}
int main()
{
test01();
system("pause");
return 0;
}
注意:
使用 erase()
函数删除元素后,原来的迭代器会失效,因此在删除元素后继续使用失效的迭代器是不安全的。如果需要在遍历 std::vector
的同时删除元素,应使用更为安全的方式,例如使用迭代器的后置递增运算符来避免迭代器失效,如下:
std::vector<int> vec = { 1, 2, 3, 4, 5 };
for (auto it = vec.begin(); it != vec.end(); /* 迭代器更新放在循环体内 */)
{
if (*it == 1)
{
it = vec.erase(it); // 删除满足条件的元素,并将迭代器指向下一个元素
}
else
{
++it; // 迭代器递增
}
}
六、vector 数据获取
示例:
#include <iostream>
#include <vector> //必须包含该头文件
using namespace std;
void test01()
{
vector<int> v1 = { 1, 2, 3, 4, 5, 6 };
cout << "v1.at(0) = " << v1.at(0) << endl;
cout << "v1[0] = " << v1[0] << endl;
cout << "v1.front() = " << v1.front() << endl;
cout << "v1.back() = " << v1.back() << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
七、vector 互换
示例:
#include <iostream>
#include <vector> //必须包含该头文件
using namespace std;
void printVec(vector<int> &v)
{
for (vector<int>::iterator At = v.begin(); At != v.end(); At++)
{
cout << *At << " ";
}
cout << endl;
}
void test01()
{
vector<int> v1 = { 1, 2, 3, 4, 5, 6 };
vector<int> v2 = { 6, 5, 4, 3, 2, 1 };
v1.swap(v2); //互换v1与v2中的元素
printVec(v1);
printVec(v2);
}
int main()
{
test01();
system("pause");
return 0;
}
八、vector 预留空间
描述:减少vector在动态扩展容量时的扩展次数
示例:
#include <iostream>
#include <vector> //必须包含该头文件
using namespace std;
void printVec(vector<int> &v)
{
for (vector<int>::iterator At = v.begin(); At != v.end(); At++)
{
cout << *At << " ";
}
cout << endl;
}
void test01()
{
vector<int> v1 = { 1, 2, 3, 4, 5, 6 };
v1.reserve(100);
printVec(v1);
cout << "v1.size() = " << v1.size() << endl;
cout << "v1.capacity() = " << v1.capacity() << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
注意:
在 C++ 中,std::vector 类提供了 reserve() 和 resize() 两个函数,用于调整 std::vector 的容量和大小。它们的区别如下:
reserve() 函数用于预留 std::vector 的容量,即为 std::vector 分配内存空间,但不会改变 std::vector 的大小。可以通过 reserve() 提前分配足够的内存空间,以减少插入元素时的内存重新分配次数,提高性能。调用 reserve() 后,std::vector 的容量将大于或等于指定的值,但实际大小仍然为 0。例如:
std::vector<int> vec;
vec.reserve(10); // 预留容量为 10
std::vector<int> vec;
vec.reserve(10); // 预留容量为 10
resize() 函数用于改变 std::vector 的大小,即调整 std::vector 中元素的个数。当指定的大小大于当前大小时,将在末尾插入新的元素;当指定的大小小于当前大小时,将删除末尾的元素。如果在扩大 std::vector 大小时,新添加的元素将使用默认构造函数进行初始化。例如:
std::vector<int> vec;
vec.resize(5); // 将 vec 的大小调整为 5,新增的元素值为 0
std::vector<int> vec;
vec.resize(5); // 将 vec 的大小调整为 5,新增的元素值为 0
需要注意的是,resize() 函数可能会导致元素的构造和析构操作,因此在调整大小时要谨慎考虑性能开销。
综上所述,reserve() 函数用于预留容量,而 resize() 函数用于调整大小。reserve() 不会改变 std::vector 的大小,而 resize() 会改变 std::vector 的大小,并可能触发元素的构造和析构操作。