оператор delete |
Здравствуйте, гость ( Вход | Регистрация )
оператор delete |
Гость_Quest_* |
5.8.2015, 0:53
Сообщение
#1
|
Гости |
Здравствуйте уважаемые программисты. У меня есть два вопроса про оператор delete.
1.) Если мы удалим указатель, который ссылается на какой-то объект, то удалиться только этот указатель ? Или объект, на который ссылается указатель, тоже удалится?? 2.) Почему в этом случае элемент вектора не удаляется ? Остается его адрес, и более того, ему присваивается какое-то значение ?
Спасибо. |
|
|
Dovgon |
5.8.2015, 6:41
Сообщение
#2
|
Студент Группа: Участник Сообщений: 92 Регистрация: 5.1.2011 Пользователь №: 2325 Спасибо сказали: 3 раз(а) Репутация: 0 |
1. идет удаление объекта
2. у вектора есть свои методы удаления данных, а ты удалил содержимое и то что ты выводишь это мусор который остался в памяти. почитай STL. |
|
|
Iron Bug |
5.8.2015, 9:51
Сообщение
#3
|
Профессионал Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: 12 |
пока у тебя слишком много непонимания принципов работы с указателями.
указатель - просто 4 байта памяти (или другое число, равное длине адреса на конкретной платформе), в этих байтах хранится, собственно, указатель - адрес некоторого пространства в памяти. когда ты вызываешь new, в памяти выделяется количество байт, необходимое для хранения типа, переданного в new, и адрес первого байта выделенной памяти записывается в указатель. при этом память, выделенная под сам указатель и память, на которую он указывает - это совершенно разные участки в памяти. оператор * получает значение, записанное в область памяти, на которую указатель указывает. указатель может быть "пустым" (NULL или nullptr в последних стандартах). что означает, что он никуда не указывает и к нему нельзя применять оператор получения значения указателя *. при этом при вызове операторов не делается никакая автоматическая проверка, валиден ли указатель. при необходимости нужно присваивать пустое значение и сравнивать указатель с NULL вручную. твой вектор содержит указатели. три места под запись некоторых адресов, 12 байт памяти. они могут либо указывать куда-то, либо быть невалидными. ты выделяешь в памяти место под три числа типа int и присваиваешь указателям их адреса. после этого ты копируешь в вектор эти адреса (при помещении в вектор происходит именно копирование). таким образом, у тебя получается, что адреса чисел хранятся в двух местах: в указателях x,y,z и в элементах вектора a. далее ты копируешь адрес одного адреса в указатель h. получается третья копия адреса. ты вызываешь delete h и это освобождает один из выделенных участков памяти под хранение числа типа int. память освобождается. но указатели никуда не деваются. просто после вызова delete все указатели на этот элемент (y, a[1] и h) невалидны. то есть, указывают на память, в которой формально хранится неизвестное значение. и, вообще говоря, попытка получить значение (оператор *) может завершиться ошибкой обращения к памяти. обычно после вызова delete указателю присваивают значение NULL (или nullptr), чтобы знать, что он указывает "в никуда". таким образом, у тебя в коде есть серьёзные проблемы: ты удалил переменную, но используешь указатель, который на неё указывал. кроме того, на неё указывают ещё два указателя, которые тоже становится опасно использовать. |
|
|
lanz |
5.8.2015, 11:41
Сообщение
#4
|
Старейший участник Группа: Участник Сообщений: 690 Регистрация: 28.12.2012 Пользователь №: 3660 Спасибо сказали: 113 раз(а) Репутация: 8 |
|
|
|
Iron Bug |
5.8.2015, 11:47
Сообщение
#5
|
Профессионал Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: 12 |
просто я всё чаще вижу, что люди пытаются писать на С++, не зная основ. я всё-таки настоятельно рекомендую начинающим твёрдо освоить С, прежде чем переходить к плюсам. там и без темплейтов много чего нужно понять, прежде чем переходить к более сложным абстракциям.
|
|
|
lanz |
5.8.2015, 14:17
Сообщение
#6
|
Старейший участник Группа: Участник Сообщений: 690 Регистрация: 28.12.2012 Пользователь №: 3660 Спасибо сказали: 113 раз(а) Репутация: 8 |
Мне кажется одним C тут не отделаешься. Нужно понимать из чего состоит и как работает компьютер (хотя бы самый простой, например AVRка). Потом нужно понимать как разные языки доходят до "железа", как программы превращаются в исполняемые файлы и т.п.
|
|
|
Гость_Quest_* |
5.8.2015, 15:23
Сообщение
#7
|
Гости |
Спасибо большое за ответы, особенно Iron Bug. Я так и думал, что удаляя указатель ( delete h; ), удаляется только объект на который он ссылается, а адрес остается, хотя он уже пустой.
А как тогда можно безопасно удалить контейнер объектов с выделенной динамически памятью ? К примеру объекты string или QPushButton (Qt). Ведь метод vector::erase() или vector::clear() просто очищают контейнер ? А освобождение памяти как тогда ? |
|
|
lanz |
5.8.2015, 15:50
Сообщение
#8
|
Старейший участник Группа: Участник Сообщений: 690 Регистрация: 28.12.2012 Пользователь №: 3660 Спасибо сказали: 113 раз(а) Репутация: 8 |
1. std::string сам следит за своей памятью, его трогать не надо (конечно только в том случае если в контейнере хранятся значения, а не указатели string*).
2. QPushButton и вообще наследники QObject имеют параметр конструктора parent, который позволяет задать того кто будет следить за их удалением, перед удалением parent удалится дочерний QObject. http://doc.qt.io/qt-5/qobject.html#QObject http://doc.qt.io/qt-5/objecttrees.html 3. Для обычных указателей можно пройтись по вектору и удалить их вручную перед очисткой. 4. Можно использовать "умные" указатели, например shared_ptr и unique_ptr. http://en.cppreference.com/w/cpp/memory/unique_ptr http://en.cppreference.com/w/cpp/memory/shared_ptr |
|
|
Гость_Quest_* |
5.8.2015, 15:58
Сообщение
#9
|
Гости |
3. Для обычных указателей можно пройтись по вектору и удалить их вручную перед очисткой. Скажите пожалуйста, такая чистка подойдет?
И что лучше, vector::erase() или vector::clear() ?? Или разницы нет никакой ? |
|
|
lanz |
5.8.2015, 16:14
Сообщение
#10
|
Старейший участник Группа: Участник Сообщений: 690 Регистрация: 28.12.2012 Пользователь №: 3660 Спасибо сказали: 113 раз(а) Репутация: 8 |
Зачем вам вообще хранить указатели на целые?
Цитата И что лучше, vector::erase() или vector::clear() ?? Или разницы нет никакой ? 15 копеек, бабушка http://www.cplusplus.com/reference/vector/vector/erase/ http://www.cplusplus.com/reference/vector/vector/clear/ Что значит "лучше"? Сообщение отредактировал lanz - 5.8.2015, 16:15 |
|
|
Текстовая версия | Сейчас: 28.3.2024, 14:45 |