Указатели, delete и nullptr

160
17 марта 2022, 23:30

Сап! Объясните максимально подробно, пожалуйста, что именно делают delete и nullptr для указателей. Вот код:

````c++
#include <bits/stdc++.h>
using namespace std;
int main(){
 int a = 5;
 int *ptr = &a;
 int *ptr_ptr = ptr;
 cout << *ptr << endl;
 cout << *ptr_ptr << endl << endl;
 delete ptr; // 1 случай
 cout << *ptr_ptr << endl;
 cout << *ptr << endl << endl;
 ptr = nullptr; // 2 случай
 cout << *ptr_ptr << endl;
 cout << *ptr << endl;
}

Собственно, вопросы:

1) Почему в случае 1 выводится 5, хотя указатель ptr был удалён?

2) Почему в случае 2 не выводится 5 и программа крашится при попытке вывести ptr?

3) Почему в случае 2 вывод ptr_ptr происходит успешно, не смотря на то, что этот указатель ссылается на ptr, при попытке вывести который программа крашится?

Answer 1

Удален - это значит, что это место помечено как свободное для другого использования, но не затерто (эта пятерка продолжает там лежать), и сама переменная, в которой хранится адрес, не изменяет своего значения. Вот вы и обращаетесь к памяти, в которой лежит ваша пятерка, но которую запросто могут переписать...

Только то, что вы делаете - НЕВЕРНО!: нельзя удалять память, не выделенную через new! Вот если бы у вас было

int * ptr = new int(5);

тогда писать delete ptr было бы можно...

А в случае 2 вы меняете значение, хранящееся в переменной, и оно не указывает никуда (т.е. такое значение - nullptr - не может быть корректным адресом чего угодно). А в ptr_ptr осталось старое значение указателя - указывающее на ту самую пятерку (а не на ptr, как вы пишете).

И вообще - запомните одно правило - освободили память - все, забудьте о ней. А если что и работает - так ведь и не каждого пешехода, перебегающего дорогу на красный свет, сбивают... Но это не значит, что его не собьют в следующий раз.

Попробую аналогию. Дома на улице - память, конверт с адресом - указатель.

int * p = new int(5);

Подписан договор аренды, в конверт p вложена бумажка с адресом дома, в дом въехала пятерка.

int *p_p = p;

В конверт p_p вложена копия бумажки из конверта p.

cout << *p << endl;

cout смотрит в конверт p, идет в дом, адрес которого там указан, смотрит, кто там живет, выводит...

delete p; // 1 случай

Договор аренды разорван, но пятерка никуда не выехала. В конверте p так и продолжает лежать адрес дома - только эта бумажка ничего не стоит: в любой момент дом может быть сдан в аренду кому-то другому и новый жилец просто выставит старого...

cout << *p_p << endl;

cout смотрит в конверт p_p, там лежит копия бумажки, которая никуда не делась. Идет в дом, адрес которого там указан, смотрит, кто там живет, выводит...

p = nullptr; // 2 случай

Из конверта p выбрасывают бумажку (заменяют ее чистой бумажкой без адреса).

cout << *p_p << endl;

В конверте p_p так и лежит бумажка со старым адресом - ее же никто не трогал... cout смотрит в конверт p_p, идет в дом, адрес которого там указан, смотрит, кто там живет, выводит...

cout << *p << endl;

cout смотрит в конверт p, обнаруживает там пустую бумажку и не знает, что делать...

READ ALSO
Что за стиль записи в структуре

Что за стиль записи в структуре

Так вот я не понимаю,зачем писать WNDCLASSEX после обЪявления структуры,вычитал где то что это создание объекта,то есть ,будто бы мы объявили WNDCLASSEX...

153
c++, нейронная сеть, перцептрон, xor, ошибка

c++, нейронная сеть, перцептрон, xor, ошибка

Пытаюсь писать простой перцептрон, который имеет только 2 вход и 1 выход и не имеет никаких скрытых слоевПерцептрон должен выполнять функцию...

97
Теорема о пробном частном C++

Теорема о пробном частном C++

Помогите разобраться в теореме Дональда Кнута: теорема о пробном частном

77