crossplatform.ru

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

2 страниц V   1 2 >  
Ответить в данную темуНачать новую тему
> оператор delete
Гость_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


Профессионал
*****

Группа: Модератор
Сообщений: 1574
Регистрация: 6.2.2009
Из: Yekaterinburg
Пользователь №: 533

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




Репутация:   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:
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Iron Bug
  опции профиля:
сообщение 5.8.2015, 11:47
Сообщение #5


Профессионал
*****

Группа: Модератор
Сообщений: 1574
Регистрация: 6.2.2009
Из: Yekaterinburg
Пользователь №: 533

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




Репутация:   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





Гости








    


Цитата(lanz @ 5.8.2015, 15:50) *
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:
http://www.cplusplus.com/reference/vector/vector/erase/
http://www.cplusplus.com/reference/vector/vector/clear/
Что значит "лучше"?

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

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


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




RSS Текстовая версия Сейчас: 24.9.2018, 22:13