Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
TierX
20 / 20 / 1
Регистрация: 28.02.2014
Сообщений: 138
#1

Возможно ли явное разрушение объекта класса? - C++

05.07.2014, 23:43. Просмотров 804. Ответов 23
Метки нет (Все метки)

Код (класс матрицы)
Кликните здесь для просмотра всего текста

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
#include <iostream>
#include <assert.h>
using namespace std;
class MATRIX_us{
private://V
    int counter;
    int row;
    int col;
    int**p;
public://CD
    MATRIX_us(int a, int b)
    {row=a;col=b;counter=0;
     p=new int*[row];
     for(int i=0;i<row;i++)
         p[i]=new int [col];
 
     for(int i=0;i<row;i++)
         for(int j=0;j<col;j++)
         p[i][j]=(11+j)+(10*i);
         cout<<"created"<<endl;}
 
    ~MATRIX_us(){
        for(int i =0;i<row;i++)
        delete []p[i];cout<<"destroyed col"<<endl;
        delete []p;   cout<<"destroyed row"<<endl;}
public://F
    void Show(int a, int b){cout << p[a][b];cout<<endl;}
    void Set(int a, int b, int c){p[a][b]=c;}
    void ShowAll(){
     for(int i=0;i<row;i++)
         for(int j=0;j<col;j++){
             cout<<p[i][j]<<' ';counter++;
             if(counter==row){cout<<endl;counter=0;}}}};
 
 
int main() {
 
    MATRIX_us a(2,2);
           //a.~MATRIX_us();  <-- ???
    system("PAUSE");
    }

Вобщем можно ли както удалить обьект класса явно? Пытался через явный вызов деструктора(с чего и началось) но класс остался полуживой.Компилятор может дальше использовать методы класса не ругаясь.
По завершению програмы вылетает:
Необработанное исключение по адресу 0x5EAE7508 (msvcr110d.dll) в удаляй1.exe: 0xC0000005: нарушение прав доступа при чтении по адресу 0xFEEEFEE2.
Без понятия что это, но явно чтото не ок. Вобщем не получаетсо. Зачем тогда предусмотрен явный вызов деструктора?

И еще интересно тот же вопрос про указатель:
1)Как инициализированый ранее указатель явно привести в нерабочюю форму (типа начального *ptr=NULL можно ли так после инициализации делать?)
2)Как удалить его.

Насколько я понимаю все обьекты/переменные/функции созданые в main идут на стек но как их оттуда удалять явно?(аля new/delete)
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
05.07.2014, 23:43
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Возможно ли явное разрушение объекта класса? (C++):

Возможно ли создание объекта шаблонного класса в функции этого класса?
Доброго времени суток, уважаемые форумчане :) Мне по лабам задали задание -...

Явное создание экземпляра класса и явная специализация шаблона класса
Всем добрый день! Не могу разобраться - эти две технологии дают один и тот же...

Создание и разрушение объектов класса, исследование вызовов конструкторов и деструкторов
Здравствуйте! Проверте пожалуйста код и подскажите мои ошибки. Согласно теме...

Объявление объекта класса fstream в качестве статической компоненты другого класса
Доброго времени суток. Есть задание, в котором говорится &quot;...Перепишите...

Проверка создания объекта класса BBB из класса AAA и работа с ним
#define @param2; // объявили для выяснения случая: нужен новый или использовать...

Указатель на объект базового класса и адрес объекта производного класса
Пример кода: class Class1 { public: Class1(int x) { j = new int;...

23
Jupiter
Каратель
Эксперт С++
6568 / 3989 / 400
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
05.07.2014, 23:51 #2
C++
1
2
3
4
5
6
7
8
9
int main()
{
    //There is no spoon
    {
          MATRIX_us a(2,2); //spoon here
    }
    //There is no spoon
    system("PAUSE");
}
Добавлено через 1 минуту
Цитата Сообщение от TierX Посмотреть сообщение
Зачем тогда предусмотрен явный вызов деструктора?
для placement new

Добавлено через 29 секунд
Цитата Сообщение от TierX Посмотреть сообщение
1)Как инициализированый ранее указатель явно привести в нерабочюю форму (типа начального *ptr=NULL можно ли так после инициализации делать?)
C++
1
ptr = 0;
1
gray_fox
What a waste!
1552 / 1257 / 165
Регистрация: 21.04.2012
Сообщений: 2,634
Завершенные тесты: 3
05.07.2014, 23:51 #3
Цитата Сообщение от TierX Посмотреть сообщение
По завершению програмы вылетает:
потому что деструктор был вызван 2 раза: явно и неявно.
Цитата Сообщение от TierX Посмотреть сообщение
Зачем тогда предусмотрен явный вызов деструктора?
Нужно при использовании placement new
Цитата Сообщение от TierX Посмотреть сообщение
Насколько я понимаю все обьекты/переменные/функции созданые в main идут на стек но как их оттуда удалять явно?(аля new/delete)
И зачем удалять их явно? Ведь для этого по сути и придуманы деструкторы - что бы в ручную не заниматься деинициализацией.
1
DrOffset
7518 / 4514 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
05.07.2014, 23:57 #4
Цитата Сообщение от TierX Посмотреть сообщение
Пытался через явный вызов деструктора(с чего и началось) но класс остался полуживой.
C++ не таков. Он не будет тебя защищать от прострела ног, рук и т.п. По стандарту обращение к данным разрушенного класса - Undefined behaviour.
Цитата Сообщение от TierX Посмотреть сообщение
По завершению програмы вылетает
Потому что деструктор вызывается второй раз. В этом суть автоматических объектов. Деструктор вызывается в конце области видимости.
Цитата Сообщение от TierX Посмотреть сообщение
Зачем тогда предусмотрен явный вызов деструктора?
Для других ситуаций. В частности вот для этого.
Цитата Сообщение от TierX Посмотреть сообщение
Насколько я понимаю все обьекты/переменные/функции созданые в main идут на стек но как их оттуда удалять явно?(аля new/delete)
На стек идут автоматические объекты. Удалять их явно оттуда не нужно. Объект живет в своей scope, в конце scope он автоматически разрушается.
Цитата Сообщение от TierX Посмотреть сообщение
типа начального *ptr=NULL можно ли так после инициализации делать?
Если до этого был new, то обязательно должен быть delete. Иначе, присвоив NULL значению указателя, мы потеряем адрес выделенной памяти и будет утечка.
Цитата Сообщение от TierX Посмотреть сообщение
Как удалить его.
Что именно нужно удалить? Указатель или объект на который он указывает?
1
TierX
20 / 20 / 1
Регистрация: 28.02.2014
Сообщений: 138
06.07.2014, 00:11  [ТС] #5
В том то и дело , что он по идее недолжен был вызываться второй раз неявно. Так как обьект должен был разрушиться. Отсюда следует, что одного деструктора недостаточно для уничтожения обьекта -> чегото не хватает->можно ли это (то чего не хватает) явно вызывать?

Ну как зачем... Чтобы удалять ненужные обьекты которые висят без дела после отработки. Создал обьект кинул в функцию->функция отработала -> в другую-> стал не нужен-> нужно удлаить. Так?
0
DrOffset
7518 / 4514 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
06.07.2014, 00:16 #6
Цитата Сообщение от TierX Посмотреть сообщение
В том то и дело , что он по идее недолжен был вызываться второй раз неявно.
Должен.
Цитата Сообщение от TierX Посмотреть сообщение
Отсюда следует, что одного деструктора недостаточно для уничтожения обьекта -> чегото не хватает->можно ли это (то чего не хватает) явно вызывать?
Достаточно. Вывод неверный.
Цитата Сообщение от TierX Посмотреть сообщение
Чтобы удалять ненужные обьекты которые висят без дела после отработки.
Ну так он и так удалится, в конце scope (области видимости), любой. В первом ответе, был создан вложенный scope, как раз для демонстрации удаления в середине main.
1
TierX
20 / 20 / 1
Регистрация: 28.02.2014
Сообщений: 138
06.07.2014, 00:17  [ТС] #7
Что именно нужно удалить? Указатель или объект на который он указывает?
Сам указатель.
Блин чото я не врублю... Если я создал обект в начале main , то он удалиться по идее только по завершению main. Значит он будет жить всё время. Но он мне уже не нужен в средине программы допустим.Могу ли я его удалить или как?
0
gray_fox
What a waste!
1552 / 1257 / 165
Регистрация: 21.04.2012
Сообщений: 2,634
Завершенные тесты: 3
06.07.2014, 00:17 #8
Цитата Сообщение от TierX Посмотреть сообщение
В том то и дело , что он по идее недолжен был вызываться второй раз неявно.
Должен - по выходу из области видимости для всех объектов вызывается деструктор в обратном порядке их (объектов) объявления (a la стек).
Цитата Сообщение от TierX Посмотреть сообщение
у как зачем... Чтобы удалять ненужные обьекты которые висят без дела после отработки. Создал обьект кинул в функцию->функция отработала -> в другую-> стал не нужен-> нужно удлаить.
Тогда ограничивай область видимости (см. пост Jupiter); либо можно написать функцию деинициализации (так же разместив её вызов в деструкторе) так, что бы при повторном вызове она ничего не делала, и дёргать её, когда захочется, но это не "C++-way".
1
DrOffset
7518 / 4514 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
06.07.2014, 00:20 #9
Цитата Сообщение от TierX Посмотреть сообщение
Сам указатель.
Сам указатель в данной ситуации - автоматический объект. Соответственно, удалится он в конце области видимости. О чем уже писалось
1
TierX
20 / 20 / 1
Регистрация: 28.02.2014
Сообщений: 138
06.07.2014, 00:26  [ТС] #10
Да я понимаю что они сами уничтожаються по окончанию области видимости. А можно ли их удять явно самому до окончания области видимости. О чом уже и спрашивалось
Если же деструктор вызываеться второй раз - значит явный вызов дестрктора не уничтожил обьект. Явный вызов деструктора != окончанию области видимости.
0
gray_fox
What a waste!
1552 / 1257 / 165
Регистрация: 21.04.2012
Сообщений: 2,634
Завершенные тесты: 3
06.07.2014, 00:35 #11
Цитата Сообщение от TierX Посмотреть сообщение
Если же деструктор вызываеться второй раз - значит явный вызов дестрктора не уничтожил обьект.
И откуда такой вывод? Вне зависимости от того, что было вызвано\ещё чего, компилятор встроит вызов деструктора в конце области видимости для всех созданных в этой области видимости объектов - таков дизайн языка, этого не поменять.
1
DrOffset
7518 / 4514 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
06.07.2014, 00:38 #12
Цитата Сообщение от TierX Посмотреть сообщение
А можно ли их удять явно самому до окончания области видимости. О чом уже и спрашивалось
Нельзя. Если нужно полный контроль за временем жизни объекта, то нужно использовать динамическое выделение памяти или\и placement new (было по ссылке выше).
Цитата Сообщение от TierX Посмотреть сообщение
Если же деструктор вызывается второй раз - значит явный вызов дестрктора не уничтожил обьект.
Уничтожил. Именно поэтому программа упала. Нельзя уничтожать второй раз то, что уже уничтожено. А вызывается он согласно модели данных, которая принята в языке. Никакой рантайм анализ как в управляемых языках не проводится на предмет того вызвал ли программер сам деструктор или нет. Это добавило бы ненужный оверхед, который не согласуется с идеологий языка ("не платим за то, что не используем").
1
TierX
20 / 20 / 1
Регистрация: 28.02.2014
Сообщений: 138
06.07.2014, 00:38  [ТС] #13
Видимо предусмотреного стандартного способа нету... Может конечно я и глупые вопросы задаю но по мне так гораздо проще удалить обьект явно, чем кутать его в скобы для неявного удаления.
Спасибо за ответы. Хоть в душе я остался не доволен
0
gray_fox
What a waste!
1552 / 1257 / 165
Регистрация: 21.04.2012
Сообщений: 2,634
Завершенные тесты: 3
06.07.2014, 00:42 #14
Цитата Сообщение от TierX Посмотреть сообщение
Видимо предусмотреного стандартного способа нету... Может конечно я и глупые вопросы задаю но по мне так горазда проще удалить обьект явно, чем кутать его в скобы для неявного удаления.
Так напиши метод деинициализации и дёргай его (прмерно так сделано в std::fstream, например), это не сложно:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class MATRIX_us {
 
   // ...
 
   void destroy() {
      if (p) {
         for (int i = 0; i != row; ++i) {
            delete[] p[i];
         }
         delete[] p;
         p = 0;
      }
   }
 
   ~MATRIX_us() {
      destroy();
   }
};
1
DrOffset
7518 / 4514 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
06.07.2014, 00:42 #15
Цитата Сообщение от TierX Посмотреть сообщение
по мне так горазда проще удалить обьект явно, чем кутать его в скобы для неявного удаления.
Не надо его кутать Это был просто пример. Нужно писать программу так, чтобы все объекты выделялись и освобождаись в свое время, время это распределять через области видимости. Короче говоря, декомпозиция и принцип "разделяй и властвуй". Если фигачить все сплошной простыней и потом сетовать, что объект нельзя удалить в середине этой простыни, то тут проблема гораздо глубже.
1
TierX
20 / 20 / 1
Регистрация: 28.02.2014
Сообщений: 138
06.07.2014, 00:47  [ТС] #16
gray_fox я несовсем понимаю чем этот вариант отличаеться от начального обычного деструктора. В чем отличие результата?

DrOffset вот какраз этого и хотелось бы... Но я надеялся на более простой способ
0
gray_fox
What a waste!
1552 / 1257 / 165
Регистрация: 21.04.2012
Сообщений: 2,634
Завершенные тесты: 3
06.07.2014, 00:53 #17
Цитата Сообщение от TierX Посмотреть сообщение
[gray_fox я несовсем понимаю чем этот вариант отличаеться от начального обычного деструктора. В чем отличие результата?
Отличается тем, что есть отдельный метод для деинициализации; можно было бы всё сделать в деструкторе, но в С++ не принято вызывать деструктор явно (кроме особых случаев). Но лучше (ИМХО) так не делать, а последовать советам из последнего поста DrOffset.
1
IGPIGP
Комп_Оратор)
Эксперт по математике/физике
7004 / 3297 / 449
Регистрация: 04.12.2011
Сообщений: 9,130
Записей в блоге: 5
06.07.2014, 01:46 #18
Цитата Сообщение от TierX Посмотреть сообщение
gray_fox я несовсем понимаю чем этот вариант отличаеться от начального обычного деструктора.
Как уже сказал DrOffset, в С++ нет сборщика мусора, который отслеживает ссылки и вызывает деструктор когда живых ссылок уже нет.
В методе деинициализации от gray_fox, происходит проверка указателя и сбрасывание его в ноль. То есть при повторном вызове деструктора он ничего на объекте делать не будет. За эту безопасность придётся платить временем на проверку.
0
TierX
20 / 20 / 1
Регистрация: 28.02.2014
Сообщений: 138
06.07.2014, 01:47  [ТС] #19
вобщем я пока вижу только 1 вариант это крепить обектты на указатель через new. чтобы потом хоть указатель и останеться но обьект можно было удалить.

Если еще кстати ктото тут будет вот например так
C++
1
MATRIX_us *p= new MATRIX_us (2,2);
понятно что все переменные/функции обьекта будут созданы в динамической памяти благодоря new. Но в самом обьекте конструктор выделяет таким же new память для значений переменных строк и столбцов.
Собсно ничо в такой круговой поруке нету страшного ?) Просто сам клас будет в одной области храниться, а для переменных в самом классе выделиться другая область. И ничего страшного да?)
0
gray_fox
What a waste!
1552 / 1257 / 165
Регистрация: 21.04.2012
Сообщений: 2,634
Завершенные тесты: 3
06.07.2014, 02:00 #20
Цитата Сообщение от TierX Посмотреть сообщение
Собсно ничо в такой круговой поруке нету страшного ?)
Ничего страшного, new просто выделяет в куче свободный участок памяти и вызывает конструктор, главное позже обеспечить соответствующий вызов delete (но с этим могут быть неудобства\проблемы, например если так же используются исключения). Вообще в "современном" С++ принято сводить ручное управление ресурсами к минимуму.
0
06.07.2014, 02:00
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
06.07.2014, 02:00
Привет! Вот еще темы с решениями:

Ошибка компиляции (преобразование объекта класса в объект другого класса)
Друзья, добрый день! Не могу понять почему выдается ошибка компиляции......

Создание объекта класса с полем являющимся объектом другого класса
Bill a; cin&gt;&gt;a;//тут я ввел с помощью перегруженного оператора ElementSpiska...

Использование объекта одного класса при создании нового класса
Добрый вечер. У меня такая проблема. Есть готовый класс L2 - список, на его...

Реализовать оператор= для присваивания объекта класса-потомка объекту базового класса
Есть два класса A и B, причем класс B является потомком A. Как реализовать...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru