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

Ошибка при резервировании памяти для своего(!) вектора - C++

Восстановить пароль Регистрация
 
Gr1f0nn
82 / 81 / 42
Регистрация: 30.09.2012
Сообщений: 408
06.07.2015, 21:53     Ошибка при резервировании памяти для своего(!) вектора #1
Всем здравствуйте!
Возможно, из названия темы не совсем понятен вопрос, поэтому уточню саму суть:
Пишу свой шаблонный класс вектора и столкнулся со странной проблемой: при вызове функции reserve, которая, если верить описанию, должна увеличить емкость вектора, если текущая емкость меньше заданной, происходит ошибка времени компиляции (если я правильно классифицировал ошибку).
Вот сама функция:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template<class T>
void array<T>::reserve(std::size_t size)
{
    if(this->capacity_ < size)
    {
        array<T> buffer(*this);
        this->clear();
        this->array_ = new T[size];
        this->capacity_ = size;
        this->size_ = buffer.size_;
 
        for(std::size_t i = 0; i < this->size_; ++i)
        {
            (*this)[i] = buffer[i];
        }
        //buffer.clear();
        //delete[] buffer.array_;
// buffer.~array();
    }
}
Если закомментировать строку, которая должна освобождать память, выделенную для объекта buffer, то все работает корректно, однако если освободить ее вручную, то происходит эта ошибка.
Почему так? Правильно ли я понимаю, что компилятор сам освободит выделенную память локального объекта? И если я ее освобождаю вручную, то он пытается вызвать дестркутор этого объекта и освободить уже освобожденную память?
Однако, не противоречит ли это правилу: "выделил память - не забудь ее освободить"?

Собственно, дестркутор и функция clear, и конструктор копирования с операций присваивания:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    ~array() { this->clear(); }
    inline void clear() { delete[] this->array_; }
template<class T>
array<T>::array(const array<T> &copy)
{
    *this = copy;
}
template<class T>
array<T>::array(const iterator beg, const iterator end)
{
    std::size_t distance = int(end) - int(beg);
    this->array_ = new T[distance];
    this->size_ = distance;
    this->capacity_ = distance;
    for(std::size_t i = 0; i < distance; ++i)
        (*this)[i] = *(beg + i);
}
Заранее спасибо!
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
06.07.2015, 21:53     Ошибка при резервировании памяти для своего(!) вектора
Посмотрите здесь:

Создание своего вектора C++
Ошибка при сохранении вектора C++
Ошибка при использовании вектора C++
C++ Ошибка при компиляции шаблонного вектора
Ошибка при выделении памяти динамически для структуры C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Max Dark
В поиске работы
 Аватар для Max Dark
1546 / 1399 / 501
Регистрация: 09.10.2013
Сообщений: 3,185
Записей в блоге: 8
Завершенные тесты: 2
06.07.2015, 22:02     Ошибка при резервировании памяти для своего(!) вектора #2
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Gr1f0nn, buffer - это локальная переменная и деструктор для нее вызовется автоматически при выходе из функции
Gr1f0nn
82 / 81 / 42
Регистрация: 30.09.2012
Сообщений: 408
06.07.2015, 22:06  [ТС]     Ошибка при резервировании памяти для своего(!) вектора #3
Cra3y, Спасибо! Я-то думал, что всегда надо освобождать выделенную память, даже для локальных объектов. Буду знать теперь =)
Max Dark
В поиске работы
 Аватар для Max Dark
1546 / 1399 / 501
Регистрация: 09.10.2013
Сообщений: 3,185
Записей в блоге: 8
Завершенные тесты: 2
06.07.2015, 22:12     Ошибка при резервировании памяти для своего(!) вектора #4
Gr1f0nn, освобождать память надо для простых указателей(int* tmp = new int[sz];) используемых только в этой функции, а лучше использовать "умные указатели" - std::shared_ptr/std::unique_ptr (#include <memory>)
Gr1f0nn
82 / 81 / 42
Регистрация: 30.09.2012
Сообщений: 408
06.07.2015, 22:14  [ТС]     Ошибка при резервировании памяти для своего(!) вектора #5
Cra3y, А разве в данном случае это не будет являться простым указателем?:
C++
1
2
3
4
5
6
7
8
9
10
template<class T>
class array
{
private:
    T* array_;
    std::size_t size_;
    std::size_t capacity_;
public:
....
};
Грубо говоря, в случае:
C++
1
2
3
4
5
6
7
8
int main()
{
    array<int> mass;
 
    for(int i = 0; i < 10; ++i)
        mass.push_back(rand()%10);
    return 0;
}
T ~ int и получается ситуация, когда int* array_ = new int[size];
Max Dark
В поиске работы
 Аватар для Max Dark
1546 / 1399 / 501
Регистрация: 09.10.2013
Сообщений: 3,185
Записей в блоге: 8
Завершенные тесты: 2
06.07.2015, 22:18     Ошибка при резервировании памяти для своего(!) вектора #6
Gr1f0nn, здесь по смыслу нужно освобождать в деструкторе, но деструктор опять же будет вызван автоматически
Gr1f0nn
82 / 81 / 42
Регистрация: 30.09.2012
Сообщений: 408
06.07.2015, 22:22  [ТС]     Ошибка при резервировании памяти для своего(!) вектора #7
Cra3y, Так, теперь яснее стало.
Но возник вопрос: бывают ли случаи, когда нужно вызвать деструктор\ освободить память вручную?
Не беря во внимание связные списки, где (насколько мне известно), чтобы что-то удалить, нужно сделать это явно, вызвав оператор delete.
Max Dark
В поиске работы
 Аватар для Max Dark
1546 / 1399 / 501
Регистрация: 09.10.2013
Сообщений: 3,185
Записей в блоге: 8
Завершенные тесты: 2
06.07.2015, 22:41     Ошибка при резервировании памяти для своего(!) вектора #8
Gr1f0nn, я не могу придумать ситуации когда нужно вызывать деструктор в ручную.
DrOffset
6423 / 3797 / 878
Регистрация: 30.01.2014
Сообщений: 6,585
06.07.2015, 22:48     Ошибка при резервировании памяти для своего(!) вектора #9
Цитата Сообщение от Gr1f0nn Посмотреть сообщение
Но возник вопрос: бывают ли случаи, когда нужно вызвать деструктор вручную?
Если объект был сконструирован через placement new.
Если объект c нетривиальными конструктором\деструктором находится внутри union (верно только в C++11).
Gr1f0nn
82 / 81 / 42
Регистрация: 30.09.2012
Сообщений: 408
06.07.2015, 22:54  [ТС]     Ошибка при резервировании памяти для своего(!) вектора #10
Cra3y, Все, кажется я понял свою ошибку в понимании, когда нужно, а когда нет вызвать дестркутор\ освобождение памяти.
В данном случае, да и в других подобных, как Вы выше и написали, дестркутор будет вызван автоматически.

Добавлено через 4 минуты
DrOffset, вот про
Цитата Сообщение от DrOffset Посмотреть сообщение
placement new.
и
Цитата Сообщение от DrOffset Посмотреть сообщение
Если объект c нетривиальными конструктором\деструктором находится внутри union (верно только в C++11).
не знал совсем. Спасибо, буду знать теперь и это.
Сам такое еще не встречал и не реализовывал. Возможно, поэтому и образовался такой пробел в знаниях ^_^
DrOffset
6423 / 3797 / 878
Регистрация: 30.01.2014
Сообщений: 6,585
06.07.2015, 22:59     Ошибка при резервировании памяти для своего(!) вектора #11
Цитата Сообщение от Gr1f0nn Посмотреть сообщение
не знал совсем.
Между тем у меня спасибка от тебя вот на это сообщение. А там как раз есть и placement new и ручной вызов деструктора.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
06.07.2015, 23:09     Ошибка при резервировании памяти для своего(!) вектора
Еще ссылки по теме:

C++ Динамическое выделение памяти для Вектора ( не STL)
C++ Ошибка памяти при выполнении, при компиляции не выводит ошибки
Ошибка при использовании for_each для вектора C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Gr1f0nn
82 / 81 / 42
Регистрация: 30.09.2012
Сообщений: 408
06.07.2015, 23:09  [ТС]     Ошибка при резервировании памяти для своего(!) вектора #12
DrOffset, Я и не знал, что это и есть тот случай

Не по теме:

тогда еще все, что касалось выделения памяти, а тем более того, как это реализовано в случае с вектором, для меня было совсем страшно и я, заглянув под спойлер, не много чего понял ^_^

Yandex
Объявления
06.07.2015, 23:09     Ошибка при резервировании памяти для своего(!) вектора
Ответ Создать тему
Опции темы

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