2013-09-24 3 views
5

Застревает в функции стирания на ch 11 excercise 11-6. Я уничтожил объекты, но я не знаю, как использовать освобождение из библиотеки allocator, чтобы вернуть пространство.Ускоренное упражнение C++ 11-6

Пожалуйста, выручите меня. PS: это не домашнее задание, но я занимаюсь дома

Ниже приведен код с Ускоренный С ++ и после этого Моё модифицированное стирание. Благодаря `

template <class T> class Vec 
{ 
public: 
    typedef T* iterator; 
    typedef const T* const_iterator; 
    typedef size_t size_type; 
    typedef T value_type; 
    typedef T& reference; 
    typedef const T& const_reference; 

    Vec() { create(); } 
    explicit Vec(size_type n, const T& t = T()) { create(n, t); } 
    Vec(const Vec& v) { create(v.begin(), v.end()); } 
    Vec& operator=(const Vec&); 
    ~Vec() { uncreate(); } 

    T& operator[](size_type i) { return data[i]; } 
    const T& operator[](size_type i) const { return data[i]; } 

    void push_back(const T& t) 
    { 
     if (avail == limit) 
     { 
      grow(); 
     } 

     unchecked_append(t); 
    } 

    iterator erase(iterator); 
    iterator erase(iterator, iterator); 
    void clear(); 

    size_type size() const { return avail - data; } 

    iterator begin() { return data; } 
    const iterator begin() const { return data; } 

    iterator end() { return avail; } 
    const iterator end() const { return avail; } 

private: 
    iterator data; 
    iterator avail; 
    iterator limit; 

    std::allocator<T> alloc; 

    void create(); 
    void create(size_type, const T&); 
    void create(const_iterator, const_iterator); 

    void uncreate(); 

    void grow(); 
    void unchecked_append(const T&); 
}; 

МОЙ КОД

template <class T> typename Vec<T>::iterator Vec<T>::erase(iterator first, iterator second) 
{ 
    if(second < first) 
    { 
     throw std::out_of_range("Iterator out of bounds."); 
    } 
    if(first < data || second >= avail) 
    { 
     throw std::out_of_range("Iterator out of bounds."); 
    } 
    iterator last = avail -1 ; 
    iterator i = first ; 
    iterator j = second ; 
    while(j <= last) 
    { 
     *i++ = *j++ ; 

    } 
    // destroy each initilsed space 
    iterator new_avail = avail - first + second ; 

    std::cout << " end " << end() << std::endl; 

    while(avail != new_avail) 
    { 
     alloc.destroy(--avail) ; 
    } 


    // dellocate space how to do that ? 
    alloc.deallocate(avail -1, ); // not sure what to do here 
    return first ; 

} 
+0

Что вы на самом деле пытаетесь сделать? – thecoshman

ответ

4

Вы не можете освободить часть выделенной памяти. То, что

alloc.deallocate (avail -1,);

не подходит.

Редактировать

Вы не должны пытаться mangage распределения в стирании. Опция, которую вы имеете, должна перераспределить ее, что сделает стирание еще более дорогостоящим . Вторая функция может выполнять:

iterator shrink(iterator first, iterator last) { 

    size_type capacity = (limit - data) - (last - first); 

    iterator new_data = alloc.allocate(capacity); 
    iterator new_avail = new_data; 
    iterator source = data; 
    while(source < first) 
     // C++11 
     alloc.construct(new_avail++, std::move(*source++)); 
    source = last; 
    iterator result = new_avail; 
    while(source < avail) 
     // C++11 
     alloc.construct(new_avail++, std::move(*source++)); 
    while(data < avail) 
     alloc.destroy(--avail); 
    data = new_data; 
    avail = new_avail; 
    limit = new_data + capacity; 

    return result; 
} 

Лучшим вариантом является этот стандартный способ. Добавьте дополнительный конструктор, подкачки и shrink_to_fit:

Vec(const_iterator first, const_iterator last) { 
    create(first, last); 
} 

void swap(Vec& other) { 
    std::swap(data, other.data); 
    ... 
} 

bool shrink_to_fit() { 
    try 
    { 
     Vec(begin(), end()).swap(*this); 
     return true; 
    } 
    catch(...) {} 
    return false; 
} 

Теперь вы можете применить несколько операций на вектор и уменьшить потребление памяти, наконец.

v.erase(a, b); 
v.erase(c, d); 
... 
v.shrink_to_fit(); 
2

Я полагаю, что один из решений является создание нового вектора со следующим размером:

new_size = old_size - number_of_elements_to_delete 

Затем копировать объекты от начала к первому стирающему объекту, от последнего стирания объекта до конца и затем отпустить старый вектор.

Это не лучшее решение, но самое простое, как я полагаю.

+0

Спасибо за ответ, я думаю, что я делаю, тоже неплохо, я просто не знаю, как использовать функцию-член освобождения от распределителя. Поэтому в основном мне нужна помощь в этом. благодаря – samprat

2

Вот что такое reference page for std::allocator::deallocate получил сказать:

void deallocate(pointer p, size_type n);

освобождает память, на который ссылается указатель p, который должен быть указателем получен предыдущим вызовом allocate(). Аргумент n должен быть равен второму аргументу вызова allocate(), который первоначально был произведен p.

То есть вы не можете освободить часть выделенного вами хранилища, только весь фрагмент.

Решение состоит в том, чтобы не вернуть хранилище, которое было освобождено по вызову erase. Просто обновите свои итераторы членов соответственно, чтобы сохранить это хранилище для последующих вызовов до create. Это то, что делает стандартный контейнер vector.

Если вы действительно хотите вернуть лишнее хранилище, выделите меньший временный фрагмент, скопируйте элементы, находящиеся в контейнере, отпустите старые итераторы хранения и обновления.

Вещь, о которой идет речь, является исключением. После того как вы выделили временный буфер, вам нужно убедиться, что вы не пропустите его в случае возникновения исключения при копировании элементов.

2

Как говорится в jrok и других, вы не можете освободить часть памяти - вам нужно освободить entire referenced storage.

Там одна более важная вещь - если вы смотрите Главу 11 (в частности, при 11.4, Dynamic ЗВТ), вы заметите, что реализация для push_back() удваивает размер основного массива, как только он достигнет текущего максимума размер.

На подобных линиях, вы хотите Halve размера базового массива, когда размер вашего вектора становится одна четвертой текущего максимального размера. Это когда вам нужно перераспределить память и вызвать std::allocator::deallocate, чтобы освободить лишнее хранилище.

Смежные вопросы