![]() |
Здравствуйте, гость ( Вход | Регистрация )
![]() ![]() |
![]() |
Гость_Quest_* |
![]()
Сообщение
#1
|
Гости ![]() |
Здравствуйте уважаемые программисты. У меня есть два вопроса про оператор delete.
1.) Если мы удалим указатель, который ссылается на какой-то объект, то удалиться только этот указатель ? Или объект, на который ссылается указатель, тоже удалится?? 2.) Почему в этом случае элемент вектора не удаляется ? Остается его адрес, и более того, ему присваивается какое-то значение ?
Спасибо. |
|
|
Dovgon |
![]()
Сообщение
#2
|
Студент ![]() Группа: Участник Сообщений: 92 Регистрация: 5.1.2011 Пользователь №: 2325 Спасибо сказали: 3 раз(а) Репутация: ![]() ![]() ![]() |
1. идет удаление объекта
2. у вектора есть свои методы удаления данных, а ты удалил содержимое и то что ты выводишь это мусор который остался в памяти. почитай STL. |
|
|
Iron Bug |
![]()
Сообщение
#3
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: ![]() ![]() ![]() |
пока у тебя слишком много непонимания принципов работы с указателями.
указатель - просто 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 |
![]()
Сообщение
#4
|
![]() Старейший участник ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 690 Регистрация: 28.12.2012 Пользователь №: 3660 Спасибо сказали: 113 раз(а) Репутация: ![]() ![]() ![]() |
|
|
|
Iron Bug |
![]()
Сообщение
#5
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: ![]() ![]() ![]() |
просто я всё чаще вижу, что люди пытаются писать на С++, не зная основ. я всё-таки настоятельно рекомендую начинающим твёрдо освоить С, прежде чем переходить к плюсам. там и без темплейтов много чего нужно понять, прежде чем переходить к более сложным абстракциям.
|
|
|
lanz |
![]()
Сообщение
#6
|
![]() Старейший участник ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 690 Регистрация: 28.12.2012 Пользователь №: 3660 Спасибо сказали: 113 раз(а) Репутация: ![]() ![]() ![]() |
Мне кажется одним C тут не отделаешься. Нужно понимать из чего состоит и как работает компьютер (хотя бы самый простой, например AVRка). Потом нужно понимать как разные языки доходят до "железа", как программы превращаются в исполняемые файлы и т.п.
|
|
|
Гость_Quest_* |
![]()
Сообщение
#7
|
Гости ![]() |
Спасибо большое за ответы, особенно Iron Bug. Я так и думал, что удаляя указатель ( delete h; ), удаляется только объект на который он ссылается, а адрес остается, хотя он уже пустой.
А как тогда можно безопасно удалить контейнер объектов с выделенной динамически памятью ? К примеру объекты string или QPushButton (Qt). Ведь метод vector::erase() или vector::clear() просто очищают контейнер ? А освобождение памяти как тогда ? |
|
|
lanz |
![]()
Сообщение
#8
|
![]() Старейший участник ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 690 Регистрация: 28.12.2012 Пользователь №: 3660 Спасибо сказали: 113 раз(а) Репутация: ![]() ![]() ![]() |
1. std::string сам следит за своей памятью, его трогать не надо (конечно только в том случае если в контейнере хранятся значения, а не указатели string*).
2. QPushButton и вообще наследники QObject имеют параметр конструктора parent, который позволяет задать того кто будет следить за их удалением, перед удалением parent удалится дочерний QObject. Link Link 3. Для обычных указателей можно пройтись по вектору и удалить их вручную перед очисткой. 4. Можно использовать "умные" указатели, например shared_ptr и unique_ptr. Link Link |
|
|
Гость_Quest_* |
![]()
Сообщение
#9
|
Гости ![]() |
Цитата(lanz @ 5.8.2015, 15:50) Link 3. Для обычных указателей можно пройтись по вектору и удалить их вручную перед очисткой. Скажите пожалуйста, такая чистка подойдет?
И что лучше, vector::erase() или vector::clear() ?? Или разницы нет никакой ? |
|
|
lanz |
![]()
Сообщение
#10
|
![]() Старейший участник ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 690 Регистрация: 28.12.2012 Пользователь №: 3660 Спасибо сказали: 113 раз(а) Репутация: ![]() ![]() ![]() |
Зачем вам вообще хранить указатели на целые?
Цитата И что лучше, vector::erase() или vector::clear() ?? Или разницы нет никакой ? 15 копеек, бабушка ![]() Link Link Что значит "лучше"? Сообщение отредактировал lanz - 5.8.2015, 16:15 |
|
|
![]() ![]() ![]() |
![]() |
|
Текстовая версия | Сейчас: 15.8.2025, 5:57 |