2016-10-08 3 views
0

У меня есть указатель указателей, что мне действительно нужно убедиться, что используемая память свободна, прежде чем приступить к выполнению других задач в программе. Я не хочу полагаться на операционную систему для управления вызовами на delete, поэтому я хочу сделать это самостоятельно, потому что позже я хочу переместить этот код на встроенную платформу с ограниченной памятью. Я написал код ниже, чтобы протестировать простой сценарий: Я выбрал int-указатель только для примера ... фактические данные могут быть чем-то другим! например Стручок или классУдаление элементов в векторе навсегда завершается

#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 секунды, чтобы заполнить вектор, но это занимает почти 17s, чтобы избавиться от него.

Код работает, для 1000000 элементов я получаю около 35 МБ памяти, а затем он начинает сокращаться примерно до 1 МБ непосредственно перед частью ожидания ожидания. Но почему это так медленно? как я могу улучшить это поведение?

Хммм .... никто не заботился о том, чтобы внимательно прочитать мой вопрос .... в любом случае это была визуальная студия, играющая в тупик ... Я запустил программу автономно, и потребовалось меньше 100 мс, чтобы заполнить и удалить вектор ! надеюсь, что этот опыт полезен для других, а

+0

Почему странный способ удаления элементов из вектора с помощью 'pop_back()'? Вам это действительно не нужно. – juanchopanza

+0

Если я этого не сделаю, видимая усадка памяти не будет –

+0

Нет, 'for (auto p: vec) delete p; vec.clear(); ' – juanchopanza

ответ

2

Улучшение тривиальна: использовать vector<int> вместо vector<int*>, так как вы храните только один элемент за указателем.

Если ваши данные больше, и вам действительно нужно хранить указатели, используйте unique_ptr или boost::ptr_vector. Это уже не 1980, вы можете использовать RAII.

Что касается медленной очистки, возможно, это связано с тем, что у вашей среды исполнения много записей в их небольших структурах распределения, и они должны пройти их все, чтобы найти правильный.

Если вам нужно иметь вектор указателей, но нужно быстрее открепление, попытайтесь держать вектор указателей, как это и сохранить фактические данные в deque -like контейнера (в list из array<data_t,32>, возможно, вы должны были бы сделайте индексирование самостоятельно, но это ускорит удаление , если это узкое место).

+0

Спасибо. Например, int *, например, фактические данные могут быть указателями некоторого сложного типа –

+2

@SaeidYazdani Это не является хорошей причиной для использования отдельно динамически выделенных объектов. – juanchopanza

+2

@SaeidYazdani более конкретная причина была бы вектором полиморфных указателей интерфейса интерфейса, и даже тогда они должны быть умными указателями. – WhozCraig