crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

2 страниц V   1 2 >  
Ответить в данную темуНачать новую тему
Гость_Quest_*
сообщение 5.8.2015, 0:53
Сообщение #1





Гости








    


Здравствуйте уважаемые программисты. У меня есть два вопроса про оператор delete.
1.) Если мы удалим указатель, который ссылается на какой-то объект, то удалиться только этот указатель ? Или объект, на который ссылается указатель, тоже удалится??

2.) Почему в этом случае элемент вектора не удаляется ? Остается его адрес, и более того, ему присваивается какое-то значение ?
int main()
{

    int *x=new int(15);
    int *y=new int(11);
    int *z=new int(7);

    vector<int*> a;
    
    a.push_back(x);
    a.push_back(y);
    a.push_back(z);
    
    int *h=a.at(1);
    delete h;
    
    for(int i(0);i<a.size();i++)
    {
        cout<<a.at(i)<<endl;   // должно быть по-идеи два элемента, а их три.
    }    

    _getch();
    return 0;
}


Спасибо.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
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  


Простите, не мог удержаться :lol:
Эскизы прикрепленных изображений
 РЈРјРµРЅСЊС€РµРЅРѕ РґРѕ 31%
Прикрепленное изображение
381 x 374 (81.63 килобайт)
 
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
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.
Link
Link
3. Для обычных указателей можно пройтись по вектору и удалить их вручную перед очисткой.
4. Можно использовать "умные" указатели, например shared_ptr и unique_ptr.
Link
Link
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Гость_Quest_*
сообщение 5.8.2015, 15:58
Сообщение #9





Гости








    


Цитата(lanz @ 5.8.2015, 15:50) Link
3. Для обычных указателей можно пройтись по вектору и удалить их вручную перед очисткой.


Скажите пожалуйста, такая чистка подойдет?
int main()
{

    int *x=new int(15);
    int *y=new int(11);
    int *z=new int(7);

    vector<int*> a;
    
    a.push_back(x);
    a.push_back(y);
    a.push_back(z);
    
    for(int i(0);i<a.size();i++)
    {
        int *h=a.at(i);
        delete h;
    }    
    a.clear();

    _getch();
    return 0;
}

И что лучше, vector::erase() или vector::clear() ?? Или разницы нет никакой ?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lanz
  опции профиля:
сообщение 5.8.2015, 16:14
Сообщение #10


Старейший участник
****

Группа: Участник
Сообщений: 690
Регистрация: 28.12.2012
Пользователь №: 3660

Спасибо сказали: 113 раз(а)




Репутация:   8  


Зачем вам вообще хранить указатели на целые?

vector<int> a;
a.push_back(1);
a.push_back(2);
a.push_back(3);


Цитата
И что лучше, vector::erase() или vector::clear() ?? Или разницы нет никакой ?

15 копеек, бабушка :lol:
Link
Link
Что значит "лучше"?

Сообщение отредактировал lanz - 5.8.2015, 16:15
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

2 страниц V   1 2 >
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0


RSS Рейтинг@Mail.ru Текстовая версия Сейчас: 15.8.2025, 5:57