C++ STL中向量大小和容量的区别
在C++ STL中,向量(vector)是一个非常强大的数据结构,它在某些方面类似于数组,但在许多方面又比数组更好用。一个向量可以动态地增长或缩小,因此它是一种非常灵活的数据结构。STL向量内部使用一个动态分配的数组来存储元素,当向向量中添加更多的元素时,STL会自动分配更多的空间以供使用。
在学习STL向量时,一个常见的问题是“大小”和“容量”的概念。这两个概念在向量的使用中非常重要,因为它们可以帮助我们理解如何使用向量,优化代码并提高程序的性能。
向量的大小和容量
在C++ STL中,一个向量的大小(size)表示该向量当前包含的元素数目。而 “容量”(capacity)表示该向量当前能够容纳的元素数目。因此,一个向量的大小永远不会大于其容量,但向量的容量可以大于其大小。
下面是一个简单的C++程序,演示如何创建和使用一个向量:
#include <iostream>
#include <vector>
using namespace std;
int main() {
// 创建一个空向量
vector<int> v;
// 在向量尾部添加元素
for (int i = 0; i < 10; i++)
v.push_back(i);
// 输出向量大小和容量
cout << "Size: " << v.size() << endl;
cout << "Capacity: " << v.capacity() << endl;
return 0;
}
该程序创建了一个空向量v,并利用push_back()函数将10个整数添加到该向量的末尾。最后,程序输出该向量的大小和容量。
输出结果为:
Size: 10
Capacity: 16
我们可以看到,该向量的大小为10,即包含了10个元素。而容量为16,即该向量当前可以容纳16个元素。这是因为在创建空向量时,STL会自动分配一些内存以用于存储元素。当向量的大小增长时,STL会在必要时自动分配更多内存以供使用。
事实上,在向量中添加元素时,STL自动为向量分配的内存可能会大于向量当前的大小。这样可以减少向量重新分配内存的次数,提高程序的性能。但是,这种效率的提高是以额外的内存空间为代价的。
接下来,我们来看一些向量的常见操作,包括如何获取、添加和删除元素,并观察这些操作对向量容量的影响。
向量的常见操作
获取元素
C++ STL向量支持使用[]运算符或at()函数获取向量中的元素。这两种方法的区别是,[]运算符不进行范围检查,如果我们试图访问越界的元素,程序会崩溃。而at()函数进行范围检查,如果越界,会抛出一个out_of_range异常。
下面是一个演示如何获取向量中元素的程序:
#include <iostream>
#include <vector>
using namespace std;
int main() {
// 创建一个向量存储一些字符串
vector<string> v{"apple", "banana", "cherry", "date"};
// 使用[]运算符获取第一个元素
cout << v[0] << endl; // 输出“apple”
// 使用at()函数获取最后一个元素
cout << v.at(v.size()-1) << endl; // 输出“date”
return 0;
}
添加元素
C++STL中,向量的添加元素的方法有两种:push_back()和insert()。
push_back()方法用于在向量的末尾添加元素,这是向量最常用的添加元素的方法。
下面是一个演示如何使用push_back()方法向向量中添加元素的程序:
#include <iostream>
#include <vector>
using namespace std;
int main() {
// 创建一个空向量
vector<int> v;
// 使用push_back()方法向向量添加一些元素
v.push_back(10);
v.push_back(20);
v.push_back(30);
// 输出向量的大小和容量
cout << "Size: " << v.size() << endl;
cout << "Capacity: " << v.capacity() << endl;
return 0;
}
输出结果为:
Size: 3
Capacity: 4
我们可以看到,向量的大小为3,容量为4。
另一种向量添加元素的方法是insert(),它可以在向量的任意位置添加元素。下面是一个演示如何使用insert()方法向向量中添加元素的程序:
#include <iostream>
#include <vector>
using namespace std;
int main() {
// 创建一个向量存储一些整数
vector<int> v{10, 20, 30, 40};
// 在向量的第三个位置插入一个元素
v.insert(v.begin()+2, 25);
// 输出向量中的所有元素
for (int i = 0; i < v.size(); i++)
cout << v[i] << " ";
cout << endl;
return 0;
}
输出结果为:
10 20 25 30 40
删除元素
删除向量中的元素通常使用erase()方法,该方法可以删除指定位置处的元素或范围内的所有元素。下面是一个演示如何使用erase()方法从向量中删除元素的程序:
#include <iostream>
#include <vector>
using namespace std;
int main() {
// 创建一个向量存储一些整数
vector<int> v{10, 20, 30, 40};
// 删除第二个元素
v.erase(v.begin()+1);
// 删除第二到第三个元素
v.erase(v.begin()+1, v.begin()+3);
// 输出向量中的所有元素
for (int i = 0; i < v.size(); i++)
cout << v[i] << " ";
cout << endl;
return 0;
}
输出结果为:
10
其中,我们首先删除了向量的第二个元素,然后删除了第二到第三个元素,最后只剩下了一个元素10。
容量的影响
在STL向量中,向量的容量大小取决于内存分配的策略。当向量的大小超出当前的容量时,STL将分配一个新的内存块,把原向量中的元素复制到新的内存块中,并释放原有内存块。由于内存分配和释放是相对于向量的容量进行的,因此这个过程可能会带来一些影响。
重新分配内存
当我们向一个向量中添加更多的元素时,向量的大小会增加,但容量可能也会随之增加。只要向量的大小小于其容量,STL就不会重新分配内存。否则,STL将分配一个新的内存块,复制原向量中的元素到新的内存块中,并释放原有内存块。
为了演示这个过程,我们可以在向向量中添加元素后,输出其大小和容量。比如下面这个程序演示了向向量中依次添加元素时,容量是如何随之增加的:
#include <iostream>
#include <vector>
using namespacestd;
int main() {
// 创建一个空向量
vector<int> v;
// 输出向量的初始大小和容量
cout << "Initial size: " << v.size() << endl;
cout << "Initial capacity: " << v.capacity() << endl;
// 向向量中依次添加元素
for (int i = 0; i < 10; i++) {
v.push_back(i);
cout << "Size: " << v.size() << ", ";
cout << "Capacity: " << v.capacity() << endl;
}
return 0;
}
输出结果为:
Initial size: 0
Initial capacity: 0
Size: 1, Capacity: 1
Size: 2, Capacity: 2
Size: 3, Capacity: 4
Size: 4, Capacity: 4
Size: 5, Capacity: 8
Size: 6, Capacity: 8
Size: 7, Capacity: 8
Size: 8, Capacity: 8
Size: 9, Capacity: 16
Size: 10, Capacity: 16
可以看到,当向量中元素个数超过容量时,STL会动态分配更多的内存以容纳更多的元素。此时,向量的大小和容量不再相等,容量可能会是原来的两倍或更多。
另外,我们可以使用reserve()方法指定向量的容量,这样当向量中的元素个数增加时,由于容量已经足够,STL就不需要再次分配内存。这样可以提高程序的性能。下面是一个演示如何使用reserve()方法指定向量容量的程序:
#include <iostream>
#include <vector>
using namespace std;
int main() {
// 创建一个空向量
vector<int> v;
// 指定向量的容量为10
v.reserve(10);
// 输出向量的初始大小和容量
cout << "Initial size: " << v.size() << endl;
cout << "Initial capacity: " << v.capacity() << endl;
// 向向量中依次添加元素
for (int i = 0; i < 10; i++) {
v.push_back(i);
cout << "Size: " << v.size() << ", ";
cout << "Capacity: " << v.capacity() << endl;
}
return 0;
}
输出结果为:
Initial size: 0
Initial capacity: 10
Size: 1, Capacity: 10
Size: 2, Capacity: 10
Size: 3, Capacity: 10
Size: 4, Capacity: 10
Size: 5, Capacity: 10
Size: 6, Capacity: 10
Size: 7, Capacity: 10
Size: 8, Capacity: 10
Size: 9, Capacity: 10
Size: 10, Capacity: 10
此时,向量的容量被指定为10,因此即使向向量中添加更多的元素,其容量也不会自动增加。
结论
在C++ STL中,向量是一种非常强大的数据结构,它可以动态地增长或缩小,因此是一种非常灵活的数据结构。当我们使用向量时,需要理解向量的大小和容量的概念,以便在使用过程中优化代码并提高程序的性能。
在向向量中添加元素时,可以使用push_back()和insert()方法。而删除元素通常使用erase()方法。同时,向量的容量大小取决于内存分配的策略,当向量的大小超出当前的容量时,STL将分配一个新的内存块,把原向量中的元素复制到新的内存块中,并释放原有内存块。因此,在向量中添加或删除元素时,我们需要理解其对容量的影响,以充分利用STL向量的优势。