【问题标题】:Memory deallocation in std::vectorstd::vector 中的内存释放
【发布时间】:2023-03-22 21:36:01
【问题描述】:

我试图弄清楚当你删除元素时 std::vector 的内存管理是如何工作的。我的理解是,一旦为向量分配了内存,没有 pop_back\erase 操作会减少向量的容量,唯一的方法是使用在 C++ 11 中引入的 shrink_to_fit。如果我是,请纠正我错误的。

【问题讨论】:

  • vector 上的操作是否减少其capacity() 取决于实现(尽管它必须在允许使迭代器/引用无效的操作期间)。 shrink_to_fit 是否实际上也减少了它的 capacity(),这取决于实现。
  • 问题是,即使您假设其他操作确实会减少容量,如果没有内存重新分配,我无法看到如何实现这一点,并且在文献中明确指出这些操作不会执行重新分配。
  • @user181218 分配器支持重新调整现有分配的大小是完全合理的。例如,C 函数realloc 就是这样做的。当然,它可能并非在所有情况下都有利可图,但如果收缩幅度足够大,它可能是有利可图的。例如,收缩可能允许分配器释放整个页面。
  • 任何允许使迭代器/引用无效的操作都可能导致重新分配。碰巧的是,这些通常是增加容量的行动。但是,理论上,insert begin() 可以重新分配向量。
  • 如果需要强制收缩:stackoverflow.com/questions/1111078/…

标签: c++ c++11 stdvector


【解决方案1】:

你是对的,大部分情况下。

只有几种方法可以减少std::vector 的容量……

移动作业

#include <iostream>
#include <vector>

int
main()
{
    std::vector<int> v1(10);
    std::vector<int> v2(20);
    std::cout << "v2.capacity() = " << v2.capacity() << '\n';
    std::cout << "Move assign v2 with less capacity\n";
    v2 = std::move(v1);
    std::cout << "v2.capacity() = " << v2.capacity() << '\n';
}

应该输出:

v2.capacity() = 20
Move assign v2 with less capacity
v2.capacity() = 10

如果涉及的分配器以某种方式设置,则无法保证容量减少。但在如上所示的常见情况下,容量会缩小。如果您真的想了解在移动分配期间容量如何不会减少的细节,请再问一个问题,我可以详细研究。

shrink_to_fit

#include <iostream>
#include <vector>

int
main()
{
    std::vector<int> v(20);
    std::cout << "v.capacity() = " << v.capacity() << '\n';
    std::cout << "erasing...\n";
    v.erase(v.begin() + v.size()/2, v.end());
    std::cout << "v.capacity() = " << v.capacity() << '\n';
    std::cout << "shrink_to_fit...\n";
    v.shrink_to_fit();
    std::cout << "v.capacity() = " << v.capacity() << '\n';
}

这将可能输出:

v.capacity() = 20
erasing...
v.capacity() = 20
shrink_to_fit...
v.capacity() = 10

但允许输出:

v.capacity() = 20
erasing...
v.capacity() = 20
shrink_to_fit...
v.capacity() = 20

交换

#include <iostream>
#include <vector>

int
main()
{
    std::vector<int> v(20);
    std::vector<int> v2(10);
    std::cout << "v.capacity() = " << v.capacity() << '\n';
    std::cout << "swap...\n";
    swap(v, v2);
    std::cout << "v.capacity() = " << v.capacity() << '\n';
}

应该输出:

v.capacity() = 20
swap...
v.capacity() = 10

我知道没有其他方法可以缩小vector 的容量(除了明显等效的结构,例如v.swap(v2))。

一个好的经验法则是向量的容量永远不会缩小,除非:

  1. 它使用另一个向量传输资源(例如移动分配或swap)。
  2. shrink_to_fit 被调用。

哦,我差点忘记了第三种可能性:任何时候你 vector 移动,从vector 移动的容量可能会减少(或者可能不会)。它是未指定的,所以你不能指望它。一般来说,移动的值应该是你不关心它们当前状态的变量。您随后将破坏它们或为其分配一个新的已知状态(分配不必通过赋值运算符;例如可以是clear(),后跟push_back())。

【讨论】:

  • 这正是我需要的摘要。非常感谢。
猜你喜欢
  • 1970-01-01
  • 2014-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-26
  • 1970-01-01
  • 1970-01-01
  • 2011-08-30
相关资源
最近更新 更多