【问题标题】:Deleting elements in vector takes forever to complete删除向量中的元素需要永远完成
【发布时间】:2016-10-08 19:53:16
【问题描述】:

我有一个指针向量,在继续程序中的其他任务之前,我确实需要确保使用的内存是空闲的。我不想依赖操作系统来管理对delete 的调用,所以我想自己做,因为稍后我想将此代码移动到内存有限的嵌入式平台。我编写了下面的代码来测试一个简单的场景: 我选择了 int 指针只是为了举例......实际数据可能是别的东西!例如POD 或类

#include <vector>
#include <iostream>
#include <Windows.h>

#define NUM_ELEMENTS    1000000

double PCFreq = 0.0;
__int64 CounterStart = 0;

void StartCounter()
{
    LARGE_INTEGER li;
    if (!QueryPerformanceFrequency(&li))
        std::cout << "QueryPerformanceFrequency failed!\r\n";

    PCFreq = double(li.QuadPart) / 1000.0;

    QueryPerformanceCounter(&li);
    CounterStart = li.QuadPart;
}
double GetCounter()
{
    LARGE_INTEGER li;
    QueryPerformanceCounter(&li);
    return double(li.QuadPart - CounterStart) / PCFreq;
}

int main()
{
    /***** CREATE VECTOR **********/
    std::cout << "Generating " << NUM_ELEMENTS 
    << " elements." << std::endl;

    StartCounter();
    std::vector<int *>* vec = new std::vector<int*>;
    for (size_t i = 0; i < NUM_ELEMENTS; i++)
    {
        vec->push_back(new int(i));
    }

    std::cout <<  vec->size() << " Have been generated in " 
    << GetCounter() << "ms" << std::endl;
    std::cout << "Destroying the vector..." << std::endl;

    /***** DELETE VECTOR **********/        

    StartCounter();

    while (!vec->empty())
    {
        delete vec->back(), vec->pop_back();
    }

    vec->clear();
    delete vec;

    std::cout << "It took " << GetCounter() << "ms to empty the vector!\r\n" 
    << "Press ENTER to exit." << std::endl; 

    //wait for key to exit
    std::cin.get();

    return 0;
}

这是控制台的输出:

Generating 1000000 elements.
1000000 Have been generated in 1077.96ms
Destroying the vector...
It took 16834.9ms to empty the vector!
Press ENTER to exit.

如您所见,填充向量大约需要 1 秒,但删除它几乎需要 17 秒。

代码有效,对于 1000000 个元素,我获得了大约 35MB 的内存,然后在等待关键部分之前它开始缩小到大约 1MB。但是为什么这么慢呢?我该如何改善这种行为?

嗯....没有人愿意仔细阅读我的问题....无论如何,这是视觉工作室在装傻...我独立运行程序,填充和删除的时间不到 100 毫秒向量!希望这个经验对其他人也有用

【问题讨论】:

  • std::vector&lt;std::unique_ptr&lt;int&gt;&gt; 怎么样?我的意思是,这已经不是 90 年代了。说真的,指向向量的指针?为什么!?
  • 如果您确实需要在向量中存储指针,请避免使用原始指针,而是使用智能指针 - 即使用 std::vector&lt;std::unique_ptr&lt;type&gt;&gt;
  • 你用了很多指针,真的有必要吗?几乎不需要动态创建向量。
  • 好吧,回答你的问题:堆分配和释放在 C 和 C++ 中是昂贵的。如果您需要快速堆,请编写您自己的自定义分配器,或使用 .NET 的托管堆。
  • 为什么需要在向量中存储指针?如果你能侥幸做到这一点,使用值会更快、更节省空间。

标签: c++ memory vector memory-leaks


【解决方案1】:

改进是微不足道的:使用vector&lt;int&gt; 而不是vector&lt;int*&gt;,因为每个指针只存储一个元素。

如果您的数据较大并且您确实需要存储指针,请使用unique_ptrboost::ptr_vector。现在已经不是 1980 年了,你可以使用 RAII。

至于清理速度慢,可能是因为您的运行时在其小的分配结构中有很多条目,并且必须遍历它们才能找到正确的条目。

如果您需要一个指针向量但需要更快的释放,请尝试保持指针向量不变,并将实际数据保存在类似deque 的容器中(也许是array&lt;data_t,32&gt;list?您必须自己进行索引保存,但它会加快删除速度如果这是瓶颈)。

【讨论】:

  • 谢谢。 int* 只是举例,实际数据可能是某种复杂类型的指针
  • @SaeidYazdani 这不是使用单独动态分配的对象的好理由。
  • @SaeidYazdani 更具体的原因是多态接口基指针的向量,即使这样,它们也应该是智能指针。
  • @SaeidYazdani Vectors 将所有数据存储在堆上,因此如果这是原因,您无需自己动态分配元素。
  • 我刚刚发现它的视觉工作室放慢了速度。我独立运行程序,填充和删除向量只用了不到 100 毫秒!
猜你喜欢
  • 2011-01-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多