Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Gr1f0nn
242 / 162 / 133
Регистрация: 30.09.2012
Сообщений: 690
#1

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

06.07.2015, 21:53. Просмотров 294. Ответов 11
Метки нет (Все метки)

Всем здравствуйте!
Возможно, из названия темы не совсем понятен вопрос, поэтому уточню саму суть:
Пишу свой шаблонный класс вектора и столкнулся со странной проблемой: при вызове функции 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);
}
Заранее спасибо!
http://www.cyberforum.ru/cpp-beginners/thread1302575.html
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
06.07.2015, 21:53
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Ошибка при резервировании памяти для своего(!) вектора (C++):

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

Ошибка при выделении памяти динамически для структуры
Есть программа. Вылетает ошибка. Если gets(BLOCKNOTE.NAME) заменить на...

Динамическое выделение памяти для Вектора ( не STL)
привет Ребят, Задание таково, прога читает слова из файла и в зависимости от...

Ошибка "Нарушение доступа для записи" при выделение памяти для поиска детерминанта квадратной матрицы
Добрый день! Делаю простое приложение по поиску детерминанта квадратной...

Создание своего вектора
Мне пришлось юзать длинку, для перевода больших чисел в разных системах...

11
Max Dark
шКодер самоучка
1890 / 1690 / 834
Регистрация: 09.10.2013
Сообщений: 3,746
Записей в блоге: 6
Завершенные тесты: 2
06.07.2015, 22:02 #2
Лучший ответ Сообщение было отмечено Gr1f0nn как решение

Решение

Gr1f0nn, buffer - это локальная переменная и деструктор для нее вызовется автоматически при выходе из функции
1
Gr1f0nn
242 / 162 / 133
Регистрация: 30.09.2012
Сообщений: 690
06.07.2015, 22:06  [ТС] #3
Cra3y, Спасибо! Я-то думал, что всегда надо освобождать выделенную память, даже для локальных объектов. Буду знать теперь =)
0
Max Dark
шКодер самоучка
1890 / 1690 / 834
Регистрация: 09.10.2013
Сообщений: 3,746
Записей в блоге: 6
Завершенные тесты: 2
06.07.2015, 22:12 #4
Gr1f0nn, освобождать память надо для простых указателей(int* tmp = new int[sz];) используемых только в этой функции, а лучше использовать "умные указатели" - std::shared_ptr/std::unique_ptr (#include <memory>)
1
Gr1f0nn
242 / 162 / 133
Регистрация: 30.09.2012
Сообщений: 690
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];
0
Max Dark
шКодер самоучка
1890 / 1690 / 834
Регистрация: 09.10.2013
Сообщений: 3,746
Записей в блоге: 6
Завершенные тесты: 2
06.07.2015, 22:18 #6
Gr1f0nn, здесь по смыслу нужно освобождать в деструкторе, но деструктор опять же будет вызван автоматически
1
Gr1f0nn
242 / 162 / 133
Регистрация: 30.09.2012
Сообщений: 690
06.07.2015, 22:22  [ТС] #7
Cra3y, Так, теперь яснее стало.
Но возник вопрос: бывают ли случаи, когда нужно вызвать деструктор\ освободить память вручную?
Не беря во внимание связные списки, где (насколько мне известно), чтобы что-то удалить, нужно сделать это явно, вызвав оператор delete.
0
Max Dark
шКодер самоучка
1890 / 1690 / 834
Регистрация: 09.10.2013
Сообщений: 3,746
Записей в блоге: 6
Завершенные тесты: 2
06.07.2015, 22:41 #8
Gr1f0nn, я не могу придумать ситуации когда нужно вызывать деструктор в ручную.
0
DrOffset
7517 / 4513 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
06.07.2015, 22:48 #9
Цитата Сообщение от Gr1f0nn Посмотреть сообщение
Но возник вопрос: бывают ли случаи, когда нужно вызвать деструктор вручную?
Если объект был сконструирован через placement new.
Если объект c нетривиальными конструктором\деструктором находится внутри union (верно только в C++11).
1
Gr1f0nn
242 / 162 / 133
Регистрация: 30.09.2012
Сообщений: 690
06.07.2015, 22:54  [ТС] #10
Cra3y, Все, кажется я понял свою ошибку в понимании, когда нужно, а когда нет вызвать дестркутор\ освобождение памяти.
В данном случае, да и в других подобных, как Вы выше и написали, дестркутор будет вызван автоматически.

Добавлено через 4 минуты
DrOffset, вот про
Цитата Сообщение от DrOffset Посмотреть сообщение
placement new.
и
Цитата Сообщение от DrOffset Посмотреть сообщение
Если объект c нетривиальными конструктором\деструктором находится внутри union (верно только в C++11).
не знал совсем. Спасибо, буду знать теперь и это.
Сам такое еще не встречал и не реализовывал. Возможно, поэтому и образовался такой пробел в знаниях ^_^
0
DrOffset
7517 / 4513 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
06.07.2015, 22:59 #11
Цитата Сообщение от Gr1f0nn Посмотреть сообщение
не знал совсем.
Между тем у меня спасибка от тебя вот на это сообщение. А там как раз есть и placement new и ручной вызов деструктора.
0
Gr1f0nn
242 / 162 / 133
Регистрация: 30.09.2012
Сообщений: 690
06.07.2015, 23:09  [ТС] #12
DrOffset, Я и не знал, что это и есть тот случай

Не по теме:

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

0
06.07.2015, 23:09
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
06.07.2015, 23:09
Привет! Вот еще темы с решениями:

Ошибка при использовании вектора
Пытаюсь проанализировать текстовый файл и посчитать кол-во каждого символа....

Ошибка при сохранении вектора
Привет всем! После сохранении в файл вектора (дин. масс.) и чтения его в...

Ошибка при обращении к элементу вектора
В общем, создаю нейросеть. Есть вектор объектов класса Слой, слой - это вектор...

Интересная ошибка при использовании Вектора
Всем доброго времени суток, столкнулся со следующей проблемой: При объявлении...


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

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru