C++的vector
是一种可变长度的动态数组,被广泛用于C++编程中。它是标准模板库(STL)中的容器之一,提供了比原始数组更灵活和方便的操作。
vector
可以存储任意类型的元素,包括基本类型(如整数和浮点数)和自定义类型(如类和结构体)。它的大小可以根据需要动态调整,而不需要手动管理内存。
vector
支持随机访问,即可以通过下标直接访问容器中的元素。它还提供了一系列的成员函数和操作符,如插入、删除和查找等,使得对元素的操作变得更加方便和高效。
vector
的内部实现使用了动态数组,当存储元素的个数超过当前容量时,会自动分配更大的内存空间,并将元素从旧的内存复制到新的内存中。这种动态分配和释放内存的特性使得vector
能够有效地处理不可预知的元素个数。
要使用vector
,首先需要包含头文件
。然后可以用vector< T >
声明一个vector
对象,其中T
表示要存储的元素类型。例如,可以使用vector< int >
来声明一个存储整数的vector
对象。
vector
是C++中非常实用的容器,它提供了简洁、高效的操作,使得动态数组的使用变得更加方便。使用vector
可以避免手动管理内存和处理数组大小的复杂逻辑。
vector提供了多种构造函数来创建和初始化vector对象。
默认构造函数:
vector();
用于创建一个空的vector。
示例:
vector<int> vec; // 创建一个空的整数类型的vector
带有初始值的构造函数:
vector(size_type count, const T& value = T());
创建包含count个元素的vector,每个元素都初始化为value的值。
示例:
vector<int> vec(5, 10); // 创建一个包含5个元素,每个元素都为10的整数类型的vector
基于范围的构造函数:
template <class InputIterator>
vector(InputIterator first, InputIterator last);
创建一个包含[first, last)范围内元素的vector。
示例:
int arr[] = {1, 2, 3, 4, 5};
vector<int> vec(arr, arr + 5); // 创建一个包含数组中所有元素的整数类型的vector
拷贝构造函数:
vector(const vector& other);
创建一个与other相同元素的vector。
示例:
vector<int> vec1(5, 10); // 创建一个包含5个元素,每个元素都为10的整数类型的vector
vector<int> vec2(vec1); // 创建一个与vec1相同元素的整数类型的vector
以上是vector的常用构造函数,可以根据具体需求选择合适的构造函数来创建vector对象。
push_back()
是vector
类的成员函数之一,用于在vector
的尾部插入一个新的元素。
push_back()
函数的语法如下:
void push_back (const value_type& val);
其中,value_type
表示vector
中存储的元素类型,val
是要插入的新元素。
示例:
#include
#include
int main() {
std::vector<int> myVector;
// 使用push_back()函数插入元素
myVector.push_back(10);
myVector.push_back(20);
myVector.push_back(30);
// 打印vector中的元素
for(int i = 0; i < myVector.size(); i++) {
std::cout << myVector[i] << " ";
}
std::cout << std::endl;
return 0;
}
输出结果为:
10 20 30
首先,我们创建了一个空的vector
对象myVector
。然后,使用三次push_back()
函数分别插入了整数值10
、20
和30
。最后,通过循环遍历vector
,打印出了vector
中的元素。
可以看到,push_back()
函数将新元素添加到了vector
的尾部。由于vector
是动态大小的,因此可以随时在尾部插入新的元素,并且vector
会自动调整大小以容纳新的元素。
需要注意的是,push_back()
函数的参数是一个常量引用,这是为了防止在插入元素时进行不必要的拷贝操作,以提高性能。
vector
的pop_back()
函数用于删除向量中的最后一个元素,并将容器的大小减1。不返回任何值。
示例:
#include
#include
int main() {
std::vector<int> vec;
// 向向量中插入元素
vec.push_back(1);
vec.push_back(2);
vec.push_back(3);
std::cout << "元素:";
for (int i : vec) {
std::cout << " " << i;
}
std::cout << std::endl;
// 使用pop_back()函数删除最后一个元素
vec.pop_back();
std::cout << "删除最后一个元素后:";
for (int i : vec) {
std::cout << " " << i;
}
std::cout << std::endl;
return 0;
}
输出结果:
元素: 1 2 3
删除最后一个元素后: 1 2
在上面的代码中,我们首先创建了一个空的vector
vec
。然后使用push_back()
函数向向量中插入三个元素(1,2,3)。接下来,我们使用pop_back()
函数删除最后一个元素。最后,我们分别使用循环打印出原始的和删除最后一个元素后的vector
。
需要注意的是,如果vector
是空的,调用pop_back()
函数将引发未定义的行为。因此,在使用pop_back()
函数之前,最好先检查vector
是否为空。可以使用empty()
函数来完成此操作。
vector
的erase
函数用于删除指定位置的元素,其原型如下:
iterator erase (iterator position);
iterator erase (iterator first, iterator last);
第一种形式的erase
函数用于删除指定位置的元素,它接受一个迭代器参数position
,表示要删除的元素的位置。该函数返回一个指向被删除元素之后元素的迭代器。
第二种形式的erase
函数用于删除指定范围内的元素,它接受两个迭代器参数first
和last
,表示要删除的范围。该函数删除范围内的所有元素,并返回一个指向最后一个被删除元素之后元素的迭代器。
示例:
#include
#include
int main() {
std::vector<int> v = {1, 2, 3, 4, 5};
// 删除指定位置的元素
std::vector<int>::iterator it = v.begin() + 2;
it = v.erase(it);
// 输出: 1 2 4 5
for (int i : v) {
std::cout << i << " ";
}
std::cout << std::endl;
// 删除指定范围内的元素
std::vector<int>::iterator first = v.begin() + 1;
std::vector<int>::iterator last = v.begin() + 3;
v.erase(first, last);
// 输出: 1 5
for (int i : v) {
std::cout << i << " ";
}
std::cout << std::endl;
return 0;
}
在上述代码中,我们首先创建了一个vector
对象v
,并初始化了5个元素。然后我们使用erase
函数删除了指定位置的元素(第3个元素),并输出了剩余的元素。接着我们使用erase
函数删除了指定范围内的元素(第2个和第3个元素),并再次输出了剩余的元素。
输出结果如下:
1 2 4 5
1 5
通过这个例子,我们可以看到使用erase
函数可以有效地删除vector
中的元素。
vector
的empty
函数可以用来检查向量是否为空。当向量为空时,返回true
;否则,返回false
。
示例:
#include
#include
int main() {
std::vector<int> numbers;
if (numbers.empty()) {
std::cout << "vector为空" << std::endl;
} else {
std::cout << "vector不为空" << std::endl;
}
numbers.push_back(10);
if (numbers.empty()) {
std::cout << "vector为空" << std::endl;
} else {
std::cout << "vector不为空" << std::endl;
}
return 0;
}
在这个例子中,开始时我们声明了一个numbers
。然后,我们使用empty
函数检查vector是否为空。由于开始时vector是空的,所以输出的结果是"vector为空"。
接着,我们使用push_back函数向vector中添加一个元素10。然后再次使用empty函数检查vector是否为空。由于vector中现在有一个元素,所以输出的结果是"vector不为空"。
通过这个例子,我们可以看到empty函数的用法和作用。它可以帮助我们判断一个vector是否为空,从而对vector进行进一步的操作。
vector
可以提供高效的随机访问。
vector
的operator[]
是一个重载运算符,用于访问vector
中的元素。它的语法是vector_name[index]
,其中vector_name
是vector
的名称,index
是要访问的元素的索引。索引从0开始,表示vector
中的第一个元素。
示例:
#include
#include
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};
// 使用operator[]访问vector中的元素
std::cout << numbers[0] << std::endl; // 输出: 1
std::cout << numbers[2] << std::endl; // 输出: 3
// 修改vector中的元素
numbers[1] = 10;
// 输出修改后的元素
std::cout << numbers[1] << std::endl; // 输出: 10
return 0;
}
在上面的示例中,我们首先创建了一个vectornumbers
并初始化了一些整数。然后,我们使用numbers[0]
和numbers[2]
访问了vector中的元素,并将它们输出到控制台上。接着,我们将第二个元素修改为10,再次使用numbers[1]
访问并输出修改后的元素。
需要注意的是,当使用operator[]
访问vector
时,如果索引超出了vector
的范围,没有元素与该索引对应,将会导致未定义行为。因此,在使用operator[]
之前,最好确保索引在合法范围内。
vector
的back
函数用于返回容器中最后一个元素的引用,即最后一个元素的值。如果容器为空,则未定义行为。
案例:
#include
#include
int main() {
std::vector<int> vec;
vec.push_back(10);
vec.push_back(20);
vec.push_back(30);
int& lastElement = vec.back(); // 获取最后一个元素的引用
std::cout << "最后一个元素的值为:" << lastElement << std::endl;
return 0;
}
运行结果:
最后一个元素的值为:30
在上述案例中,我们创建了一个名为vec
的vector
容器,并使用push_back
函数依次将数值10、20和30添加到容器中。然后,通过调用back
函数获取容器vec
中最后一个元素的引用,并将其保存在lastElement
变量中。最后,我们将所获得的最后一个元素的值打印出来。
需要注意的是,如果容器为空,那么调用back
函数将会导致未定义行为。因此,在使用back
函数之前,最好先使用empty
函数检查容器是否为空。
front()
是vector
容器的一个成员函数,用于获取容器中第一个元素的值。
示例:
#include
#include
int main() {
// 创建一个vector容器
std::vector<int> myVector;
// 向容器中添加元素
myVector.push_back(10);
myVector.push_back(20);
myVector.push_back(30);
// 使用front()函数获取容器中第一个元素的值
int firstElement = myVector.front();
// 输出第一个元素的值
std::cout << "The first element is: " << firstElement << std::endl;
return 0;
}
上面的代码首先创建了一个名为myVector
的vector
容器,并向其中添加了三个整数元素:10、20和30。然后使用front()
获取了容器中第一个元素的值,并将其赋值给了变量firstElement
。最后,通过cout
输出了第一个元素的值。
运行上述代码,将会得到如下输出结果:
The first element is: 10
需要注意的是,如果vector
容器为空,则调用front()
函数将会引发未定义行为。因此,在使用front()
之前,最好先检查vector是否为空,可以使用empty()
进行判断。
vector
的size
函数用于获取vector
中元素的数量。
示例:
#include
#include
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};
std::cout << "Size of vector numbers: " << numbers.size() << std::endl;
return 0;
}
在上述示例中,我们创建了一个名为numbers
的vector
,并初始化它包含5个整数元素。然后,我们使用size
函数获取vector
numbers
的大小,并将其打印出来。输出结果将是:
Size of vector numbers: 5
可以看到,numbers
的大小为5,即它包含5个元素。
capacity
是vector
中可以存储元素的总空间大小。
当vector
中的元素数量超过了它的容量时,vector
会自动分配更多的内存空间,以容纳更多的元素。这个过程称为动态内存分配。动态内存分配是一种消耗时间和计算资源的操作,因此vector
会在必要时一次性分配较大的内存空间,以减少动态内存分配的频率。
下面是一个案例,演示vector的capacity的变化:
#include
#include
int main() {
std::vector<int> vec;
std::cout << "Initial capacity: " << vec.capacity() << std::endl;
std::cout << "Initial size: " << vec.size() << std::endl;
// 向vector中添加元素
for (int i = 0; i < 10; i++) {
vec.push_back(i);
std::cout << "Capacity after adding element " << i << ": " << vec.capacity() << std::endl;
std::cout << "Size after adding element " << i << ": " << vec.size() << std::endl;
}
return 0;
}
输出结果为:
Initial capacity: 0
Initial size: 0
Capacity after adding element 0: 1
Size after adding element 0: 1
Capacity after adding element 1: 2
Size after adding element 1: 2
Capacity after adding element 2: 4
Size after adding element 2: 3
Capacity after adding element 3: 4
Size after adding element 3: 4
Capacity after adding element 4: 8
Size after adding element 4: 5
Capacity after adding element 5: 8
Size after adding element 5: 6
Capacity after adding element 6: 8
Size after adding element 6: 7
Capacity after adding element 7: 8
Size after adding element 7: 8
Capacity after adding element 8: 16
Size after adding element 8: 9
Capacity after adding element 9: 16
Size after adding element 9: 10
可以看到,vector
在添加元素时,当元素数量超过当前容量时,会自动增加容量。初始时,vector
的容量为0,添加第一个元素后,容量变为1;添加第二个元素后,容量变为2;添加第三个元素后,容量变为4;依次类推。当容量不足时,vector会分配更大的内存空间,容量会以指数级增长。注意,vector的容量并不等于元素的数量,它可以大于等于元素数量。
vector
的resize()
函数是用于改变vector
的大小的,它可以增加或缩小vector
的元素数量。
resize()
函数有两种形式:
resize(n)
:将vector
的大小改变为n。如果n小于当前的大小,则vector
将被截断为前n个元素。如果n大于当前的大小,则vector
的大小将增加,在末尾添加默认值的元素。
resize(n, val):将vector
的大小改变为n,并用val填充新添加的元素。如果n小于当前的大小,则vector
将被截断为前n个元素。如果n大于当前的大小,则vector
的大小将增加,新添加的元素用val填充。
示例:
#include
#include
int main() {
std::vector<int> nums = {1, 2, 3, 4, 5};
// 使用resize(n)来增加vector的大小
nums.resize(7);
std::cout << "After resize(7): ";
for (int num : nums) {
std::cout << num << " ";
}
// 输出: After resize(7): 1 2 3 4 5 0 0
// 使用resize(n, val)来增加vector的大小,并用val填充
nums.resize(10, 9);
std::cout << "\nAfter resize(10, 9): ";
for (int num : nums) {
std::cout << num << " ";
}
// 输出: After resize(10, 9): 1 2 3 4 5 0 0 9 9 9
// 使用resize(n)来缩小vector的大小
nums.resize(3);
std::cout << "\nAfter resize(3): ";
for (int num : nums) {
std::cout << num << " ";
}
// 输出: After resize(3): 1 2 3
return 0;
}
在上面的例子中,我们先创建了一个包含5个整数的vector
。然后使用resize()
函数对其进行调整大小操作。首先使用resize(7)
扩大vector
的大小,新添加了两个默认值为0的元素。然后使用resize(10, 9)
再次扩大vector
的大小,新添加了三个值为9的元素。最后使用resize(3)
缩小vector
的大小,截断了后面的元素。在每次resize
操作后,我们打印出vector
的内容来验证结果。
由于vector
的内存管理可能涉及动态分配和释放内存,这个过程可能会很耗时。为了优化性能,我们可以使用vector
的reserve
函数来预分配内存空间,以避免频繁的内存分配和释放操作。
reserve
函数的函数原型如下:
void reserve (size_type n);
参数n指定了预分配的内存空间大小,以元素个数为单位。这意味着reserve
函数将为vector
预分配至少n个元素所需的内存空间。
示例:
#include
#include
int main() {
std::vector<int> vec;
std::cout << "Before reserve: size = " << vec.size() << ", capacity = " << vec.capacity() << std::endl;
vec.reserve(100); // 预分配至少100个元素的内存空间
std::cout << "After reserve: size = " << vec.size() << ", capacity = " << vec.capacity() << std::endl;
for (int i = 0; i < 50; i++) {
vec.push_back(i);
}
std::cout << "After push_back: size = " << vec.size() << ", capacity = " << vec.capacity() << std::endl;
return 0;
}
输出结果为:
Before reserve: size = 0, capacity = 0
After reserve: size = 0, capacity = 100
After push_back: size = 50, capacity = 100
从输出结果可以看出,我们在调用reserve
函数之前,vector
的size
和capacity
都是0。调用reserve
函数之后,虽然size
仍然是0,但capacity
变为了100,预分配了100个元素的内存空间。
当我们向vector
中添加元素时,size
会发生变化,而capacity
则保持不变。可以看到,在向vector
中添加了50个元素之后,size
变为了50,而capacity
仍然是100。
这说明,通过调用reserve
函数预分配内存空间,可以有效避免频繁的内存分配和释放操作,从而提高程序的性能。
注意,reserve
函数只会增加capacity
,不会改变size
的值。