vector容器,resize/reserve/assign总结
参考 《std::vector》
vector属性
- capacity
返回当前存储空间能够容纳的元素数 - size
返回容器中的元素数,即 std::distance(begin(), end()) - max_size
此值通常反映容器大小上的理论极限,即理论上可申请到的最大容量大小。
vector成员方法
- reserve( n )
增加 vector 的容量到大于或等于 n 的大小。
若 n > capacity() ,则扩容。分配新存储,并将原空间元素拷贝到新空间内,
若 n < capacity() ,缩容?,NO,该方法不做任何事。 resize( count )
重设容器大小以容纳 count 个元素。- 若 count < size ,则减小容器元素(从尾部删除)到 count 个,
- 若 count > size ,则容器增加若干个元素,直至size == count
assign( . . )
替换容器的内容。主要有三种方式- assign( size_type count, const T& value ); 替换为 count个value
- assign( InputIt first, InputIt last ); 替换为迭代中指向的内容
- assign( std::initializer_list ilist ); 来自 initializer_list ilist 的元素替换内容
vector使用默认方式实例化产生的对象为空对象。
vector<int> vec;
if (vec.empty()) // 容器为空
{
cout << "The current size is :" << vec.size() << "\n"
<< "The available space is: " << vec.capacity() << endl;
}
有关vector::reserve()的使用
reserve()一般用作预分配容器大小,类似于数组操作的 int arr[10]
预先申请10个空间,但此时空间内的元素并没有使用。而我们之后使用 push_back() 等操作时,才会对容器内的空间进行使用。
使用场景:
vector容器是一种不定长(自增)的顺序表,原理是在我们使用时预先分配一定的空间比如10,当我们使用超过10个时,容器内部进行扩容(1.5倍或2倍扩容),扩容后容器容量为20,那么下一次扩容为40,…80 … 160 。 而每一次的扩容都需要将之前旧空间内的数据拷贝到新的空间内,会产生一定的开销。
而如果我们预先知道我们将使用到多大空间时,就可以使用reserve()一次扩容到足够的空间,节省了许多不必要的操作消耗。
下面这个小程序就测试了,10000个数据vector需要扩容24次,容量达到 12138 。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> vec;
int* ptr = vec.data(); // 0x00000000
int cnt = 0;
int num = 10000; // 测试 1万个数据,vector需要扩容几次
while (num--)
{
vec.push_back(num);
if (ptr != vec.data()) // 保存数据的首地址不同,即发生了扩容,更换了保存数据的空间位置
{
cnt++;
ptr = vec.data();
}
}
cout << "cnt = " << cnt << endl; // cnt = 24
return 0;
}
当我们修改程序,添加vec.reserve(10000); // 预先分配 10000 个空间
这样一条语句时,程序的执行结果将会是 cnt = 0 size = 10000 。
下面是对vec.reserve() 使用的测试,当我们增大扩容时,将会按照我们期望的那样操作,而当我们进行减少扩容时,此语句将会被忽略。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
// vector使用默认方式实例化产生的对象为空对象。
vector<int> vec;
if (vec.empty()) // 容器为空
{
cout << "The current size is :" << vec.size() << "\n"
<< "The available space is: " << vec.capacity() << "\n"
<< "------------------------" << endl;
}
vec.reserve(10); // 预分配容器空间,10个
cout << "The current size is :" << vec.size() << "\n" // 当前的元素个数
<< "The available space is: " << vec.capacity() << "\n"; // 当前的容量大小
for (auto const& v : vec) cout << v << " "; // 当前的元素内容
cout << "\n------------------------" << endl;
vec.reserve(5); // 预分配空间减少到 5个, 此语句无效
cout << "The current size is :" << vec.size() << "\n"
<< "The available space is: " << vec.capacity() << "\n";
for (auto const& v : vec) cout << v << " ";
cout << "\n------------------------" << endl;
return 0;
}
/*
输出:
The current size is : 0
The available space is: 0
------------------------
The current size is : 0
The available space is: 10
------------------------
The current size is : 0
The available space is: 10
------------------------
*/
有关vector::resize()的使用
resize()一般用作改变容器内现有元素的数量,有时候也可以充当初始化的手段使用。
使用vector::resize(),申请的元素默认值为0 。(当申请的元素个数 > 容器容量时,扩容)
vec.resize(5); // 申请5个元素,初始化为0
cout << "The current size is :" << vec.size() << "\n" // 当前的元素个数
<< "The available space is: " << vec.capacity() << "\n"; // 当前的容量大小
for (auto const& v : vec) cout << v << " "; // 当前的元素内容
cout << "\n------------------------" << endl;
/*
输出:
The current size is :5
The available space is: 5
0 0 0 0 0
------------------------
*/
使用vector::resize(),申请的元素,可以指定初始化的值。
使用指定初始化的申请元素时,如果是增加元素,将会保留原来的元素,对新增加的元素设置初值// vec = {0 0 0 0 0};
int a = 5;
vec.resize(10,a); // 申请10个元素,初始化为指定的变量 a
cout << "The current size is :" << vec.size() << "\n"
<< "The available space is: " << vec.capacity() << "\n";
for (auto const& v : vec) cout << v << " ";
cout << "\n------------------------" << endl;
/*
输出:
The current size is :10
The available space is: 10
0 0 0 0 0 5 5 5 5 5
------------------------
*/
使用vector::resize(),申请的元素,可以指定初始化的值。
使用指定初始化的申请元素时,如果是减少元素,则该初值无用。
具体操作过程为,从尾部开始删除元素,直至容器内元素达到要求,实际上只是修改了size属性的值。
且,减少元素的过程不会改变容器的容量。// vec = {0 0 0 0 0 5 5 5 5 5};
vec.resize(3, a); // 申请10个元素,初始化为指定的变量 a
cout << "The current size is :" << vec.size() << "\n"
<< "The available space is: " << vec.capacity() << "\n";
for (auto const& v : vec) cout << v << " ";
cout << "\n------------------------" << endl;
/*
输出:
The current size is :3
The available space is: 10
0 0 0
------------------------
*/
测试代码:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> vec;
if (vec.empty()) // 容器为空
{
cout << "The current size is :" << vec.size() << "\n"
<< "The available space is: " << vec.capacity() << "\n"
<< "------------------------" << endl;
}
vec.resize(5); // 申请5个元素,初始化为0
cout << "The current size is :" << vec.size() << "\n" // 当前的元素个数
<< "The available space is: " << vec.capacity() << "\n"; // 当前的容量大小
for (auto const& v : vec) cout << v << " "; // 当前的元素内容
cout << "\n------------------------" << endl;
int a = 5;
vec.resize(10, a); // 申请10个元素,初始化为指定的变量 a
cout << "The current size is :" << vec.size() << "\n"
<< "The available space is: " << vec.capacity() << "\n";
for (auto const& v : vec) cout << v << " ";
cout << "\n------------------------" << endl;
vec.resize(3, a); // 申请10个元素,初始化为指定的变量 a
cout << "The current size is :" << vec.size() << "\n"
<< "The available space is: " << vec.capacity() << "\n";
for (auto const& v : vec) cout << v << " ";
cout << "\n------------------------" << endl;
vec.clear(); // 清理所有元素
cout << "The current size is :" << vec.size() << "\n"
<< "The available space is: " << vec.capacity() << "\n";
for (auto const& v : vec) cout << v << " ";
cout << "\n------------------------" << endl;
/*
输出:
The current size is :0
The available space is: 0
------------------------
The current size is :5
The available space is: 5
0 0 0 0 0
------------------------
The current size is :10
The available space is: 10
0 0 0 0 0 5 5 5 5 5
------------------------
The current size is :3
The available space is: 10
0 0 0
------------------------
The current size is :0
The available space is: 10
------------------------
*/
return 0;
}
vector::reserve() 与 vector::resize() 容易被混淆,这里简单列举一下两者区别
- 首先,resize()是在我们使用容器时,进行操作的,如果容器的容量不足够我们使用,我们需要扩容。因此resize()应该具有扩容的功能。
- 而,reserve()是在我们使用容器前,进行操作的,我们需要预估容器的使用规模,从而预先分配足以容纳这些数据的容量。
下面是几个简单的例子,有助于了解具体过程。ps:vec.data()不同,表示进行了扩容。
int main()
{
vector<int> vec;
vec.reserve(100); // 预分配100个空间的容量
vec.resize(50); // 增加50个值为0的元素
cout << vec.size() << " " << vec.capacity() << " " << (void*)vec.data() << endl;
cout << "--------------------" << endl;
// resize()
// 重新申请150个元素,如果申请的数量超过空间容量,将重新分配空间
vec.resize(100); // 申请100个元素,不扩容
cout << vec.size() << " " << vec.capacity() << " " << (void*)vec.data() << endl;
vec.resize(300); // 申请300个元素, 扩容
cout << vec.size() << " " << vec.capacity() << " " << (void*)vec.data() << endl;
cout << "--------------------" << endl;
// reserve(n)
// 设置容器空间的尺寸/容量,如果 n 大于当前容量,将扩容,申请新的空间
// 如果 n 小于当前容量,无需改变空间位置
vec.reserve(50); // 缩小容量,此语句将不会生效
cout << vec.size() << " " << vec.capacity() << " " << (void*)vec.data() << endl;
vec.reserve(500); // 扩容,申请一片可以容纳500个元素的空间,将原空间元素拷贝至新的空间
cout << vec.size() << " " << vec.capacity() << " " << (void*)vec.data() << endl;
/*
输出:
50 100 013CEA50
--------------------
100 100 013CEA50
300 300 013D1C58
--------------------
300 300 013D1C58
300 500 013D2138
*/
}
有关vector::assign()的使用
assign给出的定义是替换容器的内容。其中在它的第一中使用方式与resize()非常相似。见下示例:
int main()
{
vector<int> vec1, vec2;
vec1.assign(10, 1);
cout << "The current size is :" << vec1.size() << "\n" // 当前的元素个数
<< "The available space is: " << vec1.capacity() << "\n"; // 当前的容量大小
for (auto const& v : vec1) cout << v << " "; // 当前的元素内容
cout << "\n------------------------" << endl;
vec2.resize(10, 1);
cout << "The current size is :" << vec2.size() << "\n" // 当前的元素个数
<< "The available space is: " << vec2.capacity() << "\n"; // 当前的容量大小
for (auto const& v : vec2) cout << v << " "; // 当前的元素内容
cout << "\n------------------------" << endl;
/*
输出:
The current size is :10
The available space is: 10
1 1 1 1 1 1 1 1 1 1
------------------------
The current size is :10
The available space is: 10
1 1 1 1 1 1 1 1 1 1
------------------------
*/
return 0;
}
下面通过一个测试搞清楚这两个函数的区别。
这里再次强调一下两个函数的更能定义:
- resize():重设容器大小
- assign():替换容器的内容
而正如它们定义的那样,resize会把容器的size属性的值修改,而assign会把范围内的元素全部替换,之后再把size属性的值修改。详见下面代码与测试截图:
int main()
{
vector<int> vec;
vec.assign({
1,2,3,4,5,6,7,8,9 }); // 列表初始化 std::initializer_list
cout << "The current size is :" << vec.size() << "\n" // 当前的元素个数
<< "The available space is: " << vec.capacity() << "\n"; // 当前的容量大小
for (auto const& v : vec) cout << v << " "; // 当前的元素内容
cout << "\n------------------------" << endl;
vec.assign(5, 1);
// vec.resize(5, 1);
cout << "The current size is :" << vec.size() << "\n"
<< "The available space is: " << vec.capacity() << "\n";
for (auto const& v : vec) cout << v << " ";
cout << "\n------------------------" << endl;
/*
使用vec.assign(5, 1);输出
The current size is :9
The available space is: 9
1 2 3 4 5 6 7 8 9
------------------------
The current size is :5
The available space is: 9
1 1 1 1 1
------------------------
使用vec.resize(5, 1);输出
The current size is :9
The available space is: 9
1 2 3 4 5 6 7 8 9
------------------------
The current size is :5
The available space is: 9
1 2 3 4 5
------------------------
*/
return 0;
}
还没有评论,来说两句吧...