Форум программистов, компьютерный форум CyberForum.ru

Освобождение памяти в методе класса - C++

Восстановить пароль Регистрация
 
fcshadow
0 / 0 / 0
Регистрация: 18.05.2013
Сообщений: 3
18.05.2013, 13:35     Освобождение памяти в методе класса #1
Здравствуйте,
В университете дали задание написать написать стек с итератором произвольного доступа. Собственно, класс стека и итератора я написал. Есть только одна проблема. При выполнении ф-ии pop для класса stack появляется неиспользуемая память, которая в некоторых случаях может занимать довольно большой размер. Поэтому решил написать ф-ию на подобие shrink_to_fit, т.е. уменьшить размер до размера используемой памяти.
Написал такую вот дурацкую функцию:
C++ (Qt)
1
2
3
4
5
6
7
8
9
    void shrink()
    {
        T* tmp=new T[tail-head];
        memcpy(tmp,head,sizeof(T)*(tail-head+1));
        delete [] head;
        head=tmp;
        tail=head+(tail-head);
        first=head;
    }
Ошибку вызывает строка
C++ (Qt)
1
delete [] head;
Как можно исправить данную ошибку или написать ф-ию по-другому?
Скриншот ошибки прилагаю.
Миниатюры
Освобождение памяти в методе класса  
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
OhMyGodSoLong
~ Эврика! ~
 Аватар для OhMyGodSoLong
1234 / 983 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
18.05.2013, 13:49     Освобождение памяти в методе класса #2
1. Никаких memcpy() в общем случае. Это допустимо делать только для POD-типов. Для всего остального есть цикл for и copy/move-конструкторы.
2. Почему вы выделяете памяти на (tail - head) элементов, а копируете туда на один элемент больше?
3. В чём глубинный смысл строки tail = head + (tail - head), эквивалентной tail = tail?
4. shink_to_fit() прекрасно собирается из конструктора копирования и функции swap(), обменивающей внутренние данные.
fcshadow
0 / 0 / 0
Регистрация: 18.05.2013
Сообщений: 3
18.05.2013, 14:18  [ТС]     Освобождение памяти в методе класса #3
2. Да, согласен тут я не прав. Выделяется тоже +1
3. Ну и тут тоже Я просто класс переделывал, а потом тупо заменил название одной переменной на другой.
4. А можно поподробнее как? А то я что-то не очень понимаю.

И почему все-таки нельзя писать delete[] head?

Вот функция исправленная
C++
1
2
3
4
5
6
7
8
    void shrink()
    {
        T* tmp=new T[tail-head+1];
        memcpy(tmp,head,sizeof(T)*(tail-head+1));
        tail=tmp+(tail-head);
        head=tmp;
        first=head;
    }
OhMyGodSoLong
~ Эврика! ~
 Аватар для OhMyGodSoLong
1234 / 983 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
18.05.2013, 14:36     Освобождение памяти в методе класса #4
Цитата Сообщение от fcshadow Посмотреть сообщение
И почему все-таки нельзя писать delete[] head?
Потому что проблема не в приведённом вами куске кода.

Цитата Сообщение от fcshadow Посмотреть сообщение
А можно поподробнее как? А то я что-то не очень понимаю.
Ну вот у вас есть какой-то стек:
C++
1
2
3
4
5
6
7
8
template <class T>
class stack {
// ...
private:
    T *m_data;
    size_t m_capacity; // размеры m_data
    size_t m_top; // индекс верхушки
};
Суть shrink_to_fit() — это сделать так, чтобы (m_top + 1) == m_capacity. Проблему можно разбить на два куска: 1) оставить только элементы до m_top, 2) оставить эти элементы в этом стеке, а не где-то ещё. Первая проблема в принципе решается конструктором копирования:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
template <class T>
stack<T>::stack(const stack<T> &other)
  : m_data(0)
  , m_capacity(0)
  , m_top(0)
{
    if (other.empty()) {
        return;
    }
 
    m_data = new T[other.size()];
    m_capacity = other.size();
    m_top = other.size() - 1;
    for (size_t i = 0; i < other.size(); i++) {
        m_data[i] = other.m_data[i];
    }
}
Вот только беда: правильные данные находятся в другом стеке — копии того, который передали. Но это не проблема, если есть функция swap() меняющая стеки местами:
C++
1
2
3
4
5
6
7
template <class T>
void stack<T>::swap(T &other)
{
    std::swap(m_data, other.m_data);
    std::swap(m_capacity, other.m_capacity);
    std::swap(m_top, other.m_top);
}
Теперь можно написать так:
C++
1
2
3
4
5
template <class T>
void stack<T>::shrink_to_fit()
{
    stack<T>(*this).swap(*this);
}
Делается копия текущего стека, содержащая только значащие элементы. Потом её содержимое и содержимое текущего стека меняются местами. Текущий стек содержит только значащие элементы, а содержимое временного стека будет прибито деструктором при выходе из функции.
fcshadow
0 / 0 / 0
Регистрация: 18.05.2013
Сообщений: 3
18.05.2013, 22:43  [ТС]     Освобождение памяти в методе класса #5
Понял, спасибо) мне нравится решение)
Yandex
Объявления
18.05.2013, 22:43     Освобождение памяти в методе класса
Ответ Создать тему
Опции темы

Текущее время: 09:20. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru