Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.71/21: Рейтинг темы: голосов - 21, средняя оценка - 4.71
16 / 16 / 10
Регистрация: 24.01.2014
Сообщений: 187

Об удалении указателя в деструкторе класса

15.07.2015, 22:03. Показов 4401. Ответов 23
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Изучаю C++, хочу уточнить вопрос об указателях...

Например, есть такой код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class Obj {
public:
    Obj() {};
    ~Obj() {};
protected:
 
};
 
class Test {
public:
    Test() {
        object = new Obj();
    }
 
    ~Test() {
         delete object;
    }
 
    Obj* getObj() { return object; }
protected:
Obj* object;
};
 
 
void testPtr(Obj* object) {
// Тут действия с объектом
}
 
int main() {
 
Test test;
Obj* obj = test.getObj();
 
testPtr(obj);
 
// Тут действия с объектом
 
return 0;
}
При создании класса Test, в его конструкторе, создаётся указатель на класс Obj, в деструкторе он удаляется.

А если я использую этот указатель вне класса: в функции main(), потом передаю его в другую функцию, там выполняю ещё действия с объектом...

Правильно будет удалить указатель в деструкторе класса Test и всё? В функции main ведь уже не нужно его удалять?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
15.07.2015, 22:03
Ответы с готовыми решениями:

Возникает ошибка при удалении динамического массива символов в деструкторе класса
Всем привет. Есть приватная переменная, указатель на строку wchar_t *pUAgent; В конструкторе я ее инициализирую: pUAgent =...

С++, delete в деструкторе класса не видит переменные, создаваемые new в конструкторе класса
#include "stdafx.h" #include "iostream" #include "math.h" using namespace std; class fun { double t = 0, x = 0, y = 0, z =...

Создание указателя на экземпляр класса, описанного после объявления указателя
Здравствуйте! Проблема в том, что нужно сделать так: class A{ public: B* b = nullptr; }; class B{ public:

23
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
15.07.2015, 22:21
Цитата Сообщение от WebProgrammer1 Посмотреть сообщение
Правильно будет удалить указатель в деструкторе класса Test и всё?
ага
1
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
15.07.2015, 23:02
Цитата Сообщение от WebProgrammer1 Посмотреть сообщение
При создании класса Test, в его конструкторе, создаётся указатель на класс Obj, в деструкторе он удаляется.
В конструкторе/деструкторе создаются/удаляются все члены объекта и указатель не исключение. В Вашем случае важен факт выделения памяти адресом которой будет инициализирован указатель. Часто можно встретить "удаление указателя" в смысле освобождения этой памяти и это зло (имхо). Оно исходит из буквального перевода конструкции delete ptr;
Удаление указателя как и любой переменной происходит при выходе из области если она стековая или при освобождении памяти если нет. В main Вы передаёте указатель в функцию по значению и это значит что он будет скопирован. Копия будет указывать туда же. При выходе из функции копия будет уничтожена, но память освобождена не будет.
Вроде всё нормально?
Не-а. Так как без конструктора копирования система предоставит по умолчанию побитовый клон, передача по значению класса Tect будет вызывать сбой защиты из-за попытки повторного освобождения памяти:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream> 
using namespace std;
struct Obj {
    Obj():a(0) {};
Obj(int a_):a(a_) {};
~Obj() {};
int a;
};
struct Test {
Test() {
object = new Obj();
}
~Test() {
delete object;
}
Obj* getObj() { return object; }
Obj* object;
};
void testPtr(Obj* object) {
object->a++;
}
void testVal(Test object) {
object.getObj()->a++;
}
int main() {
Test test;
Obj* obj = test.getObj();
for(int i=0; i<100; i++)
testPtr(obj);
cout<<obj->a<<endl;
testVal(test);
system("pause");
return 0;
}
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
15.07.2015, 23:22
Цитата Сообщение от IGPIGP Посмотреть сообщение
Так как без конструктора копирования система предоставит по умолчанию побитовый клон
ложь.

дефолтный конструктор делает почленный клон.

class Test - дешовенький scope-guard,
для котороых как известно,
запрещены конструкторы копирования, и удаления.

а ещё они обрабатывают ситуации с эксепшенами и прочее.

до настоящего гварда конечно далеко.


но в контексте хэлловорлда, там все впорядке.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
15.07.2015, 23:27
Цитата Сообщение от hoggy Посмотреть сообщение
почленный
Откуда терминология?
Чем побитовая копия не устраивает? И почему сразу ложь? В прокуратуре работаете?
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
15.07.2015, 23:32
Цитата Сообщение от IGPIGP Посмотреть сообщение
Откуда терминология?
стандарт языка с++
Цитата Сообщение от IGPIGP Посмотреть сообщение
Чем побитовая копия не устраивает?
запусками конструкторов копии,
которые присутствуют при почленном копировании.
Цитата Сообщение от IGPIGP Посмотреть сообщение
И почему сразу ложь?
на языке с++ то, что не является истиной - является ложью.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
15.07.2015, 23:33
Цитата Сообщение от hoggy Посмотреть сообщение
class Test - дешовенький scope-guard,
Это попытка работать в классе с указателем на другой класс. Без конструктора копии выделяющего память такая попытка плоха. Иначе достаточно функции принимающей указатель, чтобы протестировать пункт: Освобождает ли память выход из функции при удалении указателя? Тут, думаю, ТС лучше объяснит, что хотел спросить.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
15.07.2015, 23:42
Цитата Сообщение от IGPIGP Посмотреть сообщение
Это попытка работать в классе с указателем на другой класс.
не совсем.

класс Test , как примитивный скоуп-гвард, не занимается ничем, кроме захвата ресурса при создании.
и удалении его при гибели.

а вся полезная нагрузка выполняется в промежутке.

понятно, что моральные гварды запрещают себя копировать, и все такое прочее.
0
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
16.07.2015, 09:34
Цитата Сообщение от WebProgrammer1 Посмотреть сообщение
Изучаю C++, хочу уточнить вопрос об указателях...
достаточно разделить обязанности, Класс Test создает объект Obj(в куче), ну и пусть сам и удаляет
0
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906
16.07.2015, 09:40
Цитата Сообщение от IGPIGP Посмотреть сообщение
В конструкторе/деструкторе создаются/удаляются все члены объекта и указатель не исключение.
Вот я тоже позволю себе не согласиться. Можно же просто занулить указатель в конструкторе, а выделить под него память, скажем, в какой-нибудь функции Create.
Типа того
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class Arr_c
{
private:
  int *pArr;
public:
  Arr_c()
    : pArr( NULL )
    {};
  ~Arr_c()
    {
    if( pArr )
      delete []pArr;
    }
 
  void Create( int size )
    {
    pArr = new int[size];
    }
};
 
class Work_c
{
private:
  Arr_c arr;
public:
  Work_c( int size )
    {
    arr.Create( size );
    }
};
 
int main()
{
  {
  Work_c work( 77 );
  }
cin.ignore();
return 0;
}
1
16.07.2015, 09:42

Не по теме:

Цитата Сообщение от SatanaXIII Посмотреть сообщение
C++
1
2
3
4
5
~Arr_c()
 {
 if( pArr ) 
delete []pArr; 
}
омг, а Вы то чего? разрешено же делать
C++
1
delete NULL;

0
16.07.2015, 09:59

Не по теме:

aLarman, знаю, что разрешено, но не знаю чего я. Канон наверное. В любом случае нет ничего плохого.

0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
16.07.2015, 10:04
Цитата Сообщение от SatanaXIII Посмотреть сообщение
Вот я тоже позволю себе не согласиться. Можно же просто занулить указатель в конструкторе, а выделить под него память, скажем, в какой-нибудь функции Create.
Можно занулить. Можно хоть в зелёный цвет покрасить, но если он объявлен полем, то будет создан. Создание и выделение памяти (инициализация) не одно и то же. Беда в том, что даже опытные программисты постоянно путают впопыхах создание и (выделение ресурса с инициализацией), как и удаление с освобождением памяти.
Ещё раз: Под сам указатель конструктор выделит память в любом случае как и подо всё прочее. А как будет и будет ли выделяться память, адресом которой он будет инициализирован это вопрос программиста. Может и вовсе не будет инициализирован.
1
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
16.07.2015, 10:26
Цитата Сообщение от WebProgrammer1 Посмотреть сообщение
в его конструкторе, создаётся указатель на класс Obj
Создается экземпляр класса Obj, и адрес экземпляра присваивается указателю.
Цитата Сообщение от WebProgrammer1 Посмотреть сообщение
Правильно будет удалить указатель в деструкторе класса Test и всё?
Сколько раз создал, столько надо и удалить. Главное, чтобы не было попыток использовать указатель после удаления объекта.
Например, если бы main выглядела так:
C++
1
2
3
4
5
6
7
8
9
int main() {
   Obj* obj; 
   {
      Test test;
      obj = test.getObj();
   } // Здесь вызывается деструктор test
 
   testPtr(obj); // Передаем указатель на уже удаленный объект
}
то такой код будет содержать ошибку.

Цитата Сообщение от aLarman Посмотреть сообщение
разрешено же делать
C++
1
delete NULL;
Так делать всё таки нельзя Т.к. NULL - не указатель.
А вот вызывать delete на указателе, который никуда не указывает (NULL, nullptr) уже можно.

Цитата Сообщение от SatanaXIII Посмотреть сообщение
В любом случае нет ничего плохого.
Плохое в том, что это дурной пример от модератора (к тому же уже Супер-).
SatanaXIII, замещать конструктор функцией Create довольно странно в текущей ситуации.
Вызовем более 1 раза Create на одном и том же объекте и получим утечки памяти. Это плохо.
Цитата Сообщение от hoggy Посмотреть сообщение
на языке с++ то, что не является истиной - является ложью.
Ты же на русском тут с людьми общаешься, а не на C++. Мягче надо быть.
Цитата Сообщение от IGPIGP Посмотреть сообщение
И почему сразу ложь?
Есть за ним такой грешок категоричности
Цитата Сообщение от IGPIGP Посмотреть сообщение
Чем побитовая копия не устраивает?
Тем что если член имеет конструктор копирования будет вызван именно он, а не простое копирование памяти а-ля memcpy.
1
16.07.2015, 10:27

Не по теме:

Цитата Сообщение от Tulosba Посмотреть сообщение
Так делать всё таки нельзя Т.к. NULL - не указатель.
А вот вызывать delete на указателе, который никуда не указывает (NULL, nullptr) уже можно.
это был пример когда int * a == NULL :)

0
16.07.2015, 10:31

Не по теме:

Цитата Сообщение от aLarman Посмотреть сообщение
это был пример когда int * a == NULL
Я-то понял. Главное, чтобы другие новички осознали, потому и уточнил. :)

0
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906
16.07.2015, 10:49

Не по теме:

Цитата Сообщение от Tulosba Посмотреть сообщение
Плохое в том, что это дурной пример от модератора (к тому же уже Супер-).
Ну все. Теперь уж и плохой пример написать нельзя. Х)


Цитата Сообщение от Tulosba Посмотреть сообщение
Вызовем более 1 раза Create на одном и том же объекте
Само собой. Иллюстрация была другого механизма.
Единственное чем могу отмазаться в данном случае, что для повторного вызова Create надо создать еще один экземпляр Work.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
16.07.2015, 14:45

Не по теме:


Цитата Сообщение от IGPIGP Посмотреть сообщение
Под сам указатель конструктор выделит память
вот это написал! Ни слова путного, а вместе звучит. Обалдеть! :wall:



Добавлено через 8 минут
Цитата Сообщение от Tulosba Посмотреть сообщение
Тем что если член имеет конструктор копирования будет вызван именно он, а не простое копирование памяти а-ля memcpy.
Я спросил о термине "побитовая копия". А о том что " если член имеет конструктор копирования ... " я в курсе и о том же и говорил. В том плане, что нет его определения у TC. Что касается почленовщины, то не понял, в чём смысл отрицать этим создание побитовой копии когда не определён конструктор копирования?
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
16.07.2015, 15:12
Цитата Сообщение от IGPIGP Посмотреть сообщение
в чём смысл отрицать этим создание побитовой копии когда не определён конструктор копирования?
Если вообще ни для каких членов участвующих в объекте на любом уровне не определен пользовательский конструктор копирования, то можно было бы и сказать про побитовую копию. С другой стороны, я не уверен, что это будет справедливо для всех систем. Т.к. могут быть и некоторые поля заполнители для выравнивания м/у членами. Именно из-за потенциального наличия этих заполнителей для структур например не реализован по умолчанию оператор сравнения. Хотя, казалось бы, почему бы не сделать это сравнение через memcmp.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
16.07.2015, 16:49
Цитата Сообщение от IGPIGP Посмотреть сообщение
то не понял, в чём смысл отрицать этим создание побитовой копии когда не определён конструктор копирования?
когда не определен конструктор копирования,
компилятор генерирует дефолтный,
который выполняет почленное копирование всех данных членов.

для каждого члена данных запускается конструктор копии.

и вы легко можете это проверить, если создадите класс,
и залогируете запуск его конструктора копии.



Цитата Сообщение от Tulosba Посмотреть сообщение
то можно было бы и сказать про побитовую копию.
побайтовую.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
16.07.2015, 16:49
Помогаю со студенческими работами здесь

Освобождение памяти в деструкторе класса
Перечитал по этому поводу много информации. Главный вопрос. Есть класс в котором происходит динамическое выделение памяти. В...

При удалении указателя срабатывает точка останова
В принципе, в заголовке все есть... Добавлю лишь, что я всего лишь маленький ламер, камнями не кидать в случае чего... Тыкните мне носом,...

Ошибка при удалении явно заданного указателя
Помогите, пожалуйста, с этой проблемой. Уже 2 недели не могу сдать лабу &quot;main.cpp&quot; char* a=new char; char b=0; char* c=new char;...

Удалить динамический массив в деструкторе класса
Здравствуйте, есть следующий код. Хочу удалить динамический массив в деструкторе, но не выходит, не видит массив. Если описываю массив в...

Падает приложение в деструкторе дочернего класса (родители шаблонные)
Если в параметры конструктора класса Owner был передан конкретный объект Container, то: попытка вызова метода Type Container::pop()...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru