vector容器,resize/reserve/assign总结

左手的ㄟ右手 2022-11-13 11:18 284阅读 0赞

参考 《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( . . )
    替换容器的内容。主要有三种方式

    1. assign( size_type count, const T& value ); 替换为 count个value
    2. assign( InputIt first, InputIt last ); 替换为迭代中指向的内容
    3. assign( std::initializer_list ilist ); 来自 initializer_list ilist 的元素替换内容

vector使用默认方式实例化产生的对象为空对象。

  1. vector<int> vec;
  2. if (vec.empty()) // 容器为空
  3. {
  4. cout << "The current size is :" << vec.size() << "\n"
  5. << "The available space is: " << vec.capacity() << endl;
  6. }
有关vector::reserve()的使用

reserve()一般用作预分配容器大小,类似于数组操作的 int arr[10] 预先申请10个空间,但此时空间内的元素并没有使用。而我们之后使用 push_back() 等操作时,才会对容器内的空间进行使用。

使用场景:
vector容器是一种不定长(自增)的顺序表,原理是在我们使用时预先分配一定的空间比如10,当我们使用超过10个时,容器内部进行扩容(1.5倍或2倍扩容),扩容后容器容量为20,那么下一次扩容为40,…80 … 160 。 而每一次的扩容都需要将之前旧空间内的数据拷贝到新的空间内,会产生一定的开销。

而如果我们预先知道我们将使用到多大空间时,就可以使用reserve()一次扩容到足够的空间,节省了许多不必要的操作消耗。

下面这个小程序就测试了,10000个数据vector需要扩容24次,容量达到 12138 。

  1. #include <iostream>
  2. #include <vector>
  3. using namespace std;
  4. int main()
  5. {
  6. vector<int> vec;
  7. int* ptr = vec.data(); // 0x00000000
  8. int cnt = 0;
  9. int num = 10000; // 测试 1万个数据,vector需要扩容几次
  10. while (num--)
  11. {
  12. vec.push_back(num);
  13. if (ptr != vec.data()) // 保存数据的首地址不同,即发生了扩容,更换了保存数据的空间位置
  14. {
  15. cnt++;
  16. ptr = vec.data();
  17. }
  18. }
  19. cout << "cnt = " << cnt << endl; // cnt = 24
  20. return 0;
  21. }

当我们修改程序,添加vec.reserve(10000); // 预先分配 10000 个空间 这样一条语句时,程序的执行结果将会是 cnt = 0 size = 10000 。

下面是对vec.reserve() 使用的测试,当我们增大扩容时,将会按照我们期望的那样操作,而当我们进行减少扩容时,此语句将会被忽略。

  1. #include <iostream>
  2. #include <vector>
  3. using namespace std;
  4. int main()
  5. {
  6. // vector使用默认方式实例化产生的对象为空对象。
  7. vector<int> vec;
  8. if (vec.empty()) // 容器为空
  9. {
  10. cout << "The current size is :" << vec.size() << "\n"
  11. << "The available space is: " << vec.capacity() << "\n"
  12. << "------------------------" << endl;
  13. }
  14. vec.reserve(10); // 预分配容器空间,10个
  15. cout << "The current size is :" << vec.size() << "\n" // 当前的元素个数
  16. << "The available space is: " << vec.capacity() << "\n"; // 当前的容量大小
  17. for (auto const& v : vec) cout << v << " "; // 当前的元素内容
  18. cout << "\n------------------------" << endl;
  19. vec.reserve(5); // 预分配空间减少到 5个, 此语句无效
  20. cout << "The current size is :" << vec.size() << "\n"
  21. << "The available space is: " << vec.capacity() << "\n";
  22. for (auto const& v : vec) cout << v << " ";
  23. cout << "\n------------------------" << endl;
  24. return 0;
  25. }
  26. /*
  27. 输出:
  28. The current size is : 0
  29. The available space is: 0
  30. ------------------------
  31. The current size is : 0
  32. The available space is: 10
  33. ------------------------
  34. The current size is : 0
  35. The available space is: 10
  36. ------------------------
  37. */
有关vector::resize()的使用

resize()一般用作改变容器内现有元素的数量,有时候也可以充当初始化的手段使用。

  1. 使用vector::resize(),申请的元素默认值为0 。(当申请的元素个数 > 容器容量时,扩容)

    vec.resize(5); // 申请5个元素,初始化为0

    1. cout << "The current size is :" << vec.size() << "\n" // 当前的元素个数
    2. << "The available space is: " << vec.capacity() << "\n"; // 当前的容量大小
    3. for (auto const& v : vec) cout << v << " "; // 当前的元素内容
    4. cout << "\n------------------------" << endl;
    5. /*
    6. 输出:
    7. The current size is :5
    8. The available space is: 5
    9. 0 0 0 0 0
    10. ------------------------

    */

  2. 使用vector::resize(),申请的元素,可以指定初始化的值。
    使用指定初始化的申请元素时,如果是增加元素,将会保留原来的元素,对新增加的元素设置初值

    // vec = {0 0 0 0 0};

    1. int a = 5;
    2. vec.resize(10,a); // 申请10个元素,初始化为指定的变量 a
    3. cout << "The current size is :" << vec.size() << "\n"
    4. << "The available space is: " << vec.capacity() << "\n";
    5. for (auto const& v : vec) cout << v << " ";
    6. cout << "\n------------------------" << endl;
    7. /*
    8. 输出:
    9. The current size is :10
    10. The available space is: 10
    11. 0 0 0 0 0 5 5 5 5 5
    12. ------------------------

    */

  3. 使用vector::resize(),申请的元素,可以指定初始化的值。
    使用指定初始化的申请元素时,如果是减少元素,则该初值无用。
    具体操作过程为,从尾部开始删除元素,直至容器内元素达到要求,实际上只是修改了size属性的值。
    且,减少元素的过程不会改变容器的容量

    // vec = {0 0 0 0 0 5 5 5 5 5};

    1. vec.resize(3, a); // 申请10个元素,初始化为指定的变量 a
    2. cout << "The current size is :" << vec.size() << "\n"
    3. << "The available space is: " << vec.capacity() << "\n";
    4. for (auto const& v : vec) cout << v << " ";
    5. cout << "\n------------------------" << endl;
    6. /*
    7. 输出:
    8. The current size is :3
    9. The available space is: 10
    10. 0 0 0
    11. ------------------------

    */

测试代码:

  1. #include <iostream>
  2. #include <vector>
  3. using namespace std;
  4. int main()
  5. {
  6. vector<int> vec;
  7. if (vec.empty()) // 容器为空
  8. {
  9. cout << "The current size is :" << vec.size() << "\n"
  10. << "The available space is: " << vec.capacity() << "\n"
  11. << "------------------------" << endl;
  12. }
  13. vec.resize(5); // 申请5个元素,初始化为0
  14. cout << "The current size is :" << vec.size() << "\n" // 当前的元素个数
  15. << "The available space is: " << vec.capacity() << "\n"; // 当前的容量大小
  16. for (auto const& v : vec) cout << v << " "; // 当前的元素内容
  17. cout << "\n------------------------" << endl;
  18. int a = 5;
  19. vec.resize(10, a); // 申请10个元素,初始化为指定的变量 a
  20. cout << "The current size is :" << vec.size() << "\n"
  21. << "The available space is: " << vec.capacity() << "\n";
  22. for (auto const& v : vec) cout << v << " ";
  23. cout << "\n------------------------" << endl;
  24. vec.resize(3, a); // 申请10个元素,初始化为指定的变量 a
  25. cout << "The current size is :" << vec.size() << "\n"
  26. << "The available space is: " << vec.capacity() << "\n";
  27. for (auto const& v : vec) cout << v << " ";
  28. cout << "\n------------------------" << endl;
  29. vec.clear(); // 清理所有元素
  30. cout << "The current size is :" << vec.size() << "\n"
  31. << "The available space is: " << vec.capacity() << "\n";
  32. for (auto const& v : vec) cout << v << " ";
  33. cout << "\n------------------------" << endl;
  34. /*
  35. 输出:
  36. The current size is :0
  37. The available space is: 0
  38. ------------------------
  39. The current size is :5
  40. The available space is: 5
  41. 0 0 0 0 0
  42. ------------------------
  43. The current size is :10
  44. The available space is: 10
  45. 0 0 0 0 0 5 5 5 5 5
  46. ------------------------
  47. The current size is :3
  48. The available space is: 10
  49. 0 0 0
  50. ------------------------
  51. The current size is :0
  52. The available space is: 10
  53. ------------------------
  54. */
  55. return 0;
  56. }
vector::reserve() 与 vector::resize() 容易被混淆,这里简单列举一下两者区别
  • 首先,resize()是在我们使用容器时,进行操作的,如果容器的容量不足够我们使用,我们需要扩容。因此resize()应该具有扩容的功能
  • 而,reserve()是在我们使用容器前,进行操作的,我们需要预估容器的使用规模,从而预先分配足以容纳这些数据的容量。

下面是几个简单的例子,有助于了解具体过程。ps:vec.data()不同,表示进行了扩容。

  1. int main()
  2. {
  3. vector<int> vec;
  4. vec.reserve(100); // 预分配100个空间的容量
  5. vec.resize(50); // 增加50个值为0的元素
  6. cout << vec.size() << " " << vec.capacity() << " " << (void*)vec.data() << endl;
  7. cout << "--------------------" << endl;
  8. // resize()
  9. // 重新申请150个元素,如果申请的数量超过空间容量,将重新分配空间
  10. vec.resize(100); // 申请100个元素,不扩容
  11. cout << vec.size() << " " << vec.capacity() << " " << (void*)vec.data() << endl;
  12. vec.resize(300); // 申请300个元素, 扩容
  13. cout << vec.size() << " " << vec.capacity() << " " << (void*)vec.data() << endl;
  14. cout << "--------------------" << endl;
  15. // reserve(n)
  16. // 设置容器空间的尺寸/容量,如果 n 大于当前容量,将扩容,申请新的空间
  17. // 如果 n 小于当前容量,无需改变空间位置
  18. vec.reserve(50); // 缩小容量,此语句将不会生效
  19. cout << vec.size() << " " << vec.capacity() << " " << (void*)vec.data() << endl;
  20. vec.reserve(500); // 扩容,申请一片可以容纳500个元素的空间,将原空间元素拷贝至新的空间
  21. cout << vec.size() << " " << vec.capacity() << " " << (void*)vec.data() << endl;
  22. /*
  23. 输出:
  24. 50 100 013CEA50
  25. --------------------
  26. 100 100 013CEA50
  27. 300 300 013D1C58
  28. --------------------
  29. 300 300 013D1C58
  30. 300 500 013D2138
  31. */
  32. }
有关vector::assign()的使用

assign给出的定义是替换容器的内容。其中在它的第一中使用方式与resize()非常相似。见下示例:

  1. int main()
  2. {
  3. vector<int> vec1, vec2;
  4. vec1.assign(10, 1);
  5. cout << "The current size is :" << vec1.size() << "\n" // 当前的元素个数
  6. << "The available space is: " << vec1.capacity() << "\n"; // 当前的容量大小
  7. for (auto const& v : vec1) cout << v << " "; // 当前的元素内容
  8. cout << "\n------------------------" << endl;
  9. vec2.resize(10, 1);
  10. cout << "The current size is :" << vec2.size() << "\n" // 当前的元素个数
  11. << "The available space is: " << vec2.capacity() << "\n"; // 当前的容量大小
  12. for (auto const& v : vec2) cout << v << " "; // 当前的元素内容
  13. cout << "\n------------------------" << endl;
  14. /*
  15. 输出:
  16. The current size is :10
  17. The available space is: 10
  18. 1 1 1 1 1 1 1 1 1 1
  19. ------------------------
  20. The current size is :10
  21. The available space is: 10
  22. 1 1 1 1 1 1 1 1 1 1
  23. ------------------------
  24. */
  25. return 0;
  26. }

下面通过一个测试搞清楚这两个函数的区别。
这里再次强调一下两个函数的更能定义:

  • resize():重设容器大小
  • assign():替换容器的内容

而正如它们定义的那样,resize会把容器的size属性的值修改,而assign会把范围内的元素全部替换,之后再把size属性的值修改。详见下面代码与测试截图:

  1. int main()
  2. {
  3. vector<int> vec;
  4. vec.assign({
  5. 1,2,3,4,5,6,7,8,9 }); // 列表初始化 std::initializer_list
  6. cout << "The current size is :" << vec.size() << "\n" // 当前的元素个数
  7. << "The available space is: " << vec.capacity() << "\n"; // 当前的容量大小
  8. for (auto const& v : vec) cout << v << " "; // 当前的元素内容
  9. cout << "\n------------------------" << endl;
  10. vec.assign(5, 1);
  11. // vec.resize(5, 1);
  12. cout << "The current size is :" << vec.size() << "\n"
  13. << "The available space is: " << vec.capacity() << "\n";
  14. for (auto const& v : vec) cout << v << " ";
  15. cout << "\n------------------------" << endl;
  16. /*
  17. 使用vec.assign(5, 1);输出
  18. The current size is :9
  19. The available space is: 9
  20. 1 2 3 4 5 6 7 8 9
  21. ------------------------
  22. The current size is :5
  23. The available space is: 9
  24. 1 1 1 1 1
  25. ------------------------
  26. 使用vec.resize(5, 1);输出
  27. The current size is :9
  28. The available space is: 9
  29. 1 2 3 4 5 6 7 8 9
  30. ------------------------
  31. The current size is :5
  32. The available space is: 9
  33. 1 2 3 4 5
  34. ------------------------
  35. */
  36. return 0;
  37. }

在这里插入图片描述
在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,284人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Vector容器

    Vector 容器 一、 简介 vector 是将元素置于一个动态数组中加以管理的容器 vector可以随机存取元素(支持索引值直接存取,用\[\]操作符或at()函数)

    相关 Vector容器

    一、vector容器。 1、vector容器基本概念。 1)功能: vector容器数据结构与数组非常相似,也称为单端数组。 2)vector与普通数组区别?