【问题标题】:C++11 memory release in variable reassignment变量重新分配中的 C++11 内存释放
【发布时间】:2015-10-16 18:21:37
【问题描述】:

我正在尝试更多地了解 C++ 中如何处理内存,并且我有一个关于重新分配变量时如何释放内存的问题。为了监控内存消耗,我有一个(Linux 特定的)函数CheckMem(),它调用pmap 来查看进程正在使用多少内存。 然后我简单地创建一个大小为 1 的向量,将其重新分配给大小为 100 万的向量,然后再次将其重新分配给大小为 1,并观察内存如何变化。

#include <iostream>
#include <vector>
#include <sstream>
#include <cstdio>
#include <unistd.h>

using namespace std;

void CheckMem()
{
  char cmdstring[100],outbuf[500],buf[100];
  sprintf(cmdstring,"pmap -x %d | tail -1",getpid()); 
  FILE* output = popen(cmdstring,"r");
  fgets(outbuf,500,output);
  size_t kb,rss,dirty;
  istringstream ss(outbuf);
  ss >> cmdstring >> buf >> kb >> rss >> dirty;
  cout << "RSS: " << rss << " KB" << endl;
}

int main()
{
 vector<double> vd(1);
 CheckMem();
 vd = vector<double>(1000000);
 CheckMem();
 vd = vector<double>(1);
 CheckMem();
 return 0;
}

如果我使用 g++(gcc 版本 4.8.4)编译,我会得到以下输出:

RSS: 1184 KB
RSS: 9128 KB
RSS: 9136 KB

当向量重新分配为大小 1 时,用于大向量(100 万倍 ~ 8 MB)的内存似乎没有释放。 但是,如果我使用标志-std=c++11 进行编译,那么输出会发生变化:

RSS: 1180 KB
RSS: 9112 KB
RSS: 1300 KB

现在内存似乎被重新分配释放了。 C++11 标准是否以某种方式对重新分配的内存进行了不同的处理?

【问题讨论】:

    标签: c++ linux c++11 memory vector


    【解决方案1】:

    库的实现者很可能会重用向量的容量,只要它大于您分配给它的向量的容量。这样他们就节省了内存分配。

    从 C++11 开始,我们有移动赋值,因此当您使用 -std=c++11 编译而不是重用容量时,临时向量被移动到现有向量中,原始向量的内容被移动到临时向量中。在表达式结束时,临时对象被销毁,您现在拥有一个容量较小的向量。

    如果您想缩小向量的容量,您应该查看:reduce the capacity of an stl vector

    【讨论】:

    • 是的。这似乎是怎么回事。如果我添加一个vector&lt;double&gt;(0).swap(vd),那么这两种情况都会释放内存。
    • 引用指出它在哪里声明或暗示分配给向量重用分配自向量存储的地方会很有用。上次我看的时候,我以为那是未指定的,但我可能记错了。
    • @Yakk 我说很有可能来说明这可能不是问题,但它可能是。我应该再澄清一下吗?
    【解决方案2】:

    不同之处在于 C++11 中引入的移动赋值。在此之前,您只有复制构造函数,如果容量足够大,它会将您的新向量复制到旧向量中。

    使用 C++11 和 move 分配新向量的数据替换旧的数据,然后将其销毁。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-02
      • 1970-01-01
      • 2013-02-28
      • 1970-01-01
      • 2012-04-10
      相关资源
      最近更新 更多