Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.75/8: Рейтинг темы: голосов - 8, средняя оценка - 4.75
84 / 83 / 8
Регистрация: 31.03.2015
Сообщений: 447
1

Правильно ли написан деструктор?

02.03.2016, 13:32. Показов 1506. Ответов 18
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Вопрос, правильно ли я написал деструктор. Должно удалить переменную из памяти CAR И ссылку НА CDR, но сам по себе обьект CDR не трогать.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
union value {
    char letter;
    char *bytes;
    unsigned int number;
    
};
 
class Cell {
private:
    value * CAR;
    Cell * CDR;
public: 
    Cell(value * CAR);
    Cell(value * CAR, Cell * CDR);
    Cell();
    ~Cell();
    value * getCAR();
    Cell * getCDR();
    void setCAR(value * CAR);
    void setCDR(Cell * CDR);
};
C++
1
2
3
4
Cell::~Cell() {
    delete CAR;
    *CDR = nullptr;
}
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
02.03.2016, 13:32
Ответы с готовыми решениями:

правильно ли написан код в с++?
#include <iostream> #include <map> #include <fstream> using namespace std; int main() { ...

Правильно ли написан код
Извините, подправьте плиз, всем заранее огромное спасибо #include<iostream.h>...

Правильно ли написан код .cpp?
Вот сам код #define _CRT_SECURE_NO_WARNINGS #include <Windows.h> #include <HCNetSDK.h> ...

Правильно ли написан класс DigitalTimeException
Помогите пожалуйста, с созданием класса. Необходимон аписать класс - DigitalTimeException со...

18
Эксперт по математике/физике
3390 / 1913 / 571
Регистрация: 09.04.2015
Сообщений: 5,365
02.03.2016, 13:43 2
Если была выделена память под CAR.bytes, то она будет потеряна
1
1375 / 519 / 72
Регистрация: 21.07.2015
Сообщений: 1,304
02.03.2016, 13:45 3
Цитата Сообщение от Vaderkos Посмотреть сообщение
*CDR = nullptr;
В чем сакральный смысл смысл этой строчки?
Цитата Сообщение от Vaderkos Посмотреть сообщение
но сам по себе обьект CDR не трогать.
Если член класса нужен после удаления объекта класса, то стоит его оттуда вынести в другое место.

Добавлено через 1 минуту
Цитата Сообщение от Vaderkos Посмотреть сообщение
И ссылку НА CDR
Указатель CDR и так удалится после вызова деструктора.
1
84 / 83 / 8
Регистрация: 31.03.2015
Сообщений: 447
02.03.2016, 14:25  [ТС] 4
Цитата Сообщение от shmkv Посмотреть сообщение
В чем сакральный смысл смысл этой строчки?
Обнулить указатель?

Я так понял что удаляя delete CAR освоболится память и удалиться указатель на него. А ссылка на cdr мне не нужна, поэтому обнулил
0
1375 / 519 / 72
Регистрация: 21.07.2015
Сообщений: 1,304
02.03.2016, 14:27 5
Цитата Сообщение от Vaderkos Посмотреть сообщение
Обнулить указатель
В чем смысл обнулять указатель объекта, которого уже не будет существовать?
Цитата Сообщение от Vaderkos Посмотреть сообщение
удалиться указатель на него
Нет, delete с указателем ничего не делает.
0
84 / 83 / 8
Регистрация: 31.03.2015
Сообщений: 447
02.03.2016, 14:28  [ТС] 6
Цитата Сообщение от shmkv Посмотреть сообщение
Указатель CDR и так удалится после вызова деструктора.
ага то есть можно вот так оставить
C++
1
2
3
Cell::~Cell() {
    delete CAR;
}
Добавлено через 1 минуту
shmkv, сам обьект cdr мне нужен, и на него будет другой указатель, а обьект car и указатель на него не нужен.
0
1375 / 519 / 72
Регистрация: 21.07.2015
Сообщений: 1,304
02.03.2016, 14:28 7
Цитата Сообщение от Vaderkos Посмотреть сообщение
можно вот так оставить
Не знаю, твоей реализации не видел. Обычно класс должен подчищать за собой все выделенные ресурсы.
0
84 / 83 / 8
Регистрация: 31.03.2015
Сообщений: 447
02.03.2016, 14:36  [ТС] 8
shmkv, Но ведь Cell содержит только ссылку на CDR, то если я обнулю указатель, с самим cdr ниего не случиться
0
Эксперт по математике/физике
3390 / 1913 / 571
Регистрация: 09.04.2015
Сообщений: 5,365
02.03.2016, 14:37 9
Цитата Сообщение от Vaderkos Посмотреть сообщение
delete CAR
подавая эту команду в деструкторе Вы удалите объект.
Если Вам объект нужен то можно просто обнулить указатель, как Вы сделали, а можно не обнулять, так как по завершению деструктора указатель вместе с объектом (не CAR, а class Cell ) будет удален
1
Эксперт .NET
12079 / 8388 / 1281
Регистрация: 21.01.2016
Сообщений: 31,601
02.03.2016, 14:39 10
Обнулять указатель нужно всегда, даже в деструкторе. Это не удалит объект, естественно, но сделает указатель недействительным в явном виде. Так, что товарищ Vaderkos, правильно поступил. Однако, он допустил ошибку - обнулять указатель нужно так CDR = nullptr;, а не так *CDR = nullptr;
1
84 / 83 / 8
Регистрация: 31.03.2015
Сообщений: 447
02.03.2016, 14:40  [ТС] 11
Usaga, То есть с самого начала было как надо) Спасибо.
C++
1
2
3
4
Cell::~Cell() {
    delete CAR;
    *CDR = nullptr;
}
0
Эксперт .NET
12079 / 8388 / 1281
Регистрация: 21.01.2016
Сообщений: 31,601
02.03.2016, 14:43 12
Лучший ответ Сообщение было отмечено Vaderkos как решение

Решение

Vaderkos, было почти правильно. Нужно так: CDR = nullptr; т.е. без звёздочки.
1
1375 / 519 / 72
Регистрация: 21.07.2015
Сообщений: 1,304
02.03.2016, 14:49 13
Цитата Сообщение от Usaga Посмотреть сообщение
Обнулять указатель нужно всегда, даже в деструкторе.
После уничтожения объекта обращение к нему - UB, хоть 10 раз обнули указатель.
Цитата Сообщение от Vaderkos Посмотреть сообщение
То есть с самого начала было как надо)
Нет, не нужно.
1
Эксперт .NET
12079 / 8388 / 1281
Регистрация: 21.01.2016
Сообщений: 31,601
02.03.2016, 14:52 14
Цитата Сообщение от shmkv Посмотреть сообщение
После уничтожения объекта обращение к нему - UB, хоть 10 раз обнули указатель.
Если вы уничтожите объект, а потом обратитесь к нему, то это UB (которое может и не вызвать падения программы), а вот разыменовывание нулевого указателя вылезет сразу же. Что резко снизит количество времени затраченного на отладку.
0
1375 / 519 / 72
Регистрация: 21.07.2015
Сообщений: 1,304
02.03.2016, 14:58 15
Цитата Сообщение от Usaga Посмотреть сообщение
Что резко снизит количество времени затраченного на отладку.
Давайте не будем касаться вопросов не относящихся к теме, в частности вопросов отладки. Если есть необходимость защитить себя от типичных ошибок с указателями, то лучше их вообще не использовать в явном виде. Этому вполне способствуют средства С++11.

Добавлено через 1 минуту
Ну и современные компилятор в дебаге обычно неплохо отлавливают сами такие вещи.
0
Эксперт .NET
12079 / 8388 / 1281
Регистрация: 21.01.2016
Сообщений: 31,601
02.03.2016, 15:05 16
Обнуление указателей в теле объекта - приведение этого объекта в явно невалидную форму. Это хорошая практика и она напрямую относится к теме с деструкторами. А вот современные компиляторы и С++11 уж точно не относятся к теме.

Код деструктора освобождает ресурсы занятые объектом (delete Car) и приводит его поля в неинициализированное состояние (Car = nullptr). Тут всё правильно. Нельзя за собой мусор оставлять, даже если этот мусор - ненужный указатель указывающий "в никуда".
0
1375 / 519 / 72
Регистрация: 21.07.2015
Сообщений: 1,304
02.03.2016, 15:10 17
Цитата Сообщение от Usaga Посмотреть сообщение
приведение этого объекта в явно невалидную форм
Ок. Начнем с того, что разыменование null pointer не на каждой платформе вызывает падение, это раз. Сразу после разрушения объекта его память может занять другой, который перепишет твой nullptr, это два. Хороший компилятор и отладчик надежней для этих целей, это три.
Из бессмысленного спора выйду.
0
Эксперт .NET
12079 / 8388 / 1281
Регистрация: 21.01.2016
Сообщений: 31,601
02.03.2016, 15:29 18
Я бы не сказал, что спор бессмысленный.

Я бы не стал надеяться на хороший компилятор и на платформу, особенно, если учесть, что не у всех бывает выбор какой компилятор использовать. Обнулять указатели - практика хорошая (но не панацея, я согласен). Могу только добавить, что такая практика мне несколько раз помогала. Но я не настаиваю.
0
693 / 303 / 99
Регистрация: 04.07.2014
Сообщений: 846
02.03.2016, 16:05 19
Сколько же тут ошибок во всём.

0. Замени CAR и CDR на более длинные имена, а то отличие в одну букву и та посередине, Это и не читабельно и вероятность опечатки слишком большая.
1. Нарушил правило пяти
2. Ты видимо не понимаешь, что тут делается
Цитата Сообщение от Vaderkos Посмотреть сообщение
C++
1
*CDR = nullptr;
Так как у твоего конструктора нет спецификатора explicit, то происходит неявное преобразование типов,
Это тоже самое, что
C++
1
*CDR = CDR(nullptr);
Долго пытался, что-то сделать из твоего кода:

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
40
41
42
43
44
45
46
47
48
49
50
include <iostream>
 
class Foo {
private:
  int* m_data;
  Foo*  m_next;
public:
  Foo(int* data) {
    m_data =data;
    m_next = nullptr;
    std::cout << "INFO: Foo(data=" << m_data << ", next=" << m_next << ")\n";
  }
  Foo(int* data, Foo* next) {
    m_data = data;
    m_next = next;
    std::cout << "INFO: Foo(data=" << m_data << ", next=" << m_next << ")\n";
  }
  ~Foo() {
    std::cout << "INFO: ~Foo(data=" << m_data << ", next=" << m_next << ")\n";
    delete m_data;
    if (m_next) // Без проверки, следующая строка является местом отказа
      *m_next = nullptr; // Ошибка, тоже самое что *m_next=Foo(nullptr), неявное приведение типов
  }
  // Выполняем правило пяти:
  Foo(const Foo& right) = default;
  Foo& operator=(const Foo& right) = default;
  Foo(Foo&& right) = default;
  Foo& operator=(Foo&& right) = default;
  int* getData() {
    return m_data;
  }
};
 
int main() {
  int* a = new int(10);
  int* b = new int(20);
  Foo* first = new Foo(a);
  Foo* second = new Foo(b, first);
  std::cout << "Address data of first:  ";
    std::cout << first->getData() << std::endl;
  std::cout << "Address data of second: ";
    std::cout << second->getData() << std::endl;
  delete second;
  std::cout << "Address data of first:  ";
    std::cout << first->getData() << std::endl;
  delete first;
  delete b; // Ошибка, уже удаляли
  delete a; // Ошибка, уже удаляли
  return 0;
}
Результат:
Bash
1
2
3
4
5
6
7
8
9
INFO: Foo(data=0x73b010, next=0)
INFO: Foo(data=0x73b030, next=0x73b050)
Address data of first:  0x73b010
Address data of second: 0x73b030
INFO: ~Foo(data=0x73b030, next=0x73b050)
INFO: Foo(data=0, next=0)
INFO: ~Foo(data=0, next=0)
Address data of first:  0
INFO: ~Foo(data=0, next=0)
1
02.03.2016, 16:05
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
02.03.2016, 16:05
Помогаю со студенческими работами здесь

Найти сумму ряда (правильно ли написан код?)
#include &lt;iostream&gt; #include &lt;math.h&gt; using namespace std; int main() { int i,s,res=(i)*(i);...

Правильно ли написан default конструктор, инициализирующий объект нулем (0/1)
Правильно ли написан default конструктор кот инициализует объект как 0 (0/1): class Rational...

Как правильно должен быть написан метод возвращающий ссылку на вектор
Доброе время форумчане! Ну собственно сама тема говорит Есть класс class SoftwareCore {...

Деструктор класса. Как правильно очистить память?
Добрый день! Написал прогу бинарного дерева поиска, все работает, но нужен совет как убрать за...


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

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru