быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
1

в классе создаётся объект оператором new, как его удалить после использования в основной программе? delete в вызывающей функции не вариант!

26.06.2011, 22:40. Показов 4673. Ответов 55
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Собсно


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//Это типа служебного класса. (Внимание! В оригинальном коде он вложен в класс xx, но я этого не стал делать, дабы не усложнять код!)
class nemo_ {
};
 
//А это вот класс для конечного пользователя
class xx {
 public:
  nemo_& funktsia () {
  nemo_* ne= new nemo_ [1];
  return *ne;
 };
};
 
int main () {
 xx m;
 
 //Так, вот щас создастся объект класса nemo_; а нужен он для того, чтобы выполнился определённый код, который в нём скрывается
 m.funktsia ();
 //Тут пойдёт всякий разный код, и мне объект nemo_ больше не нужен
}
Вот как удалить объект класса nemo? Указателя не него в main нет, создать указатель в main НЕ ПРЕДЛАГАТЬ ибо это что же получается, конечный пользователь будет пользоваться классом xx и потом ещё должен будет заботиться об удалении nemo_, о котором он знать ничего не знает? Это не наш метод, наш метод даже не знаю какой, по-моему придётся смириться с утечкой памяти, пусть после m.funktsia (); объект типа nemo_ существует до конца проги. Так что ли?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
26.06.2011, 22:40
Ответы с готовыми решениями:

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


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

Или воспользуйтесь поиском по форуму:
55
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
27.06.2011, 01:45  [ТС] 21
Author24 — интернет-сервис помощи студентам
Цитата Сообщение от grizlik78 Посмотреть сообщение
Для автоматический объект явно деструктор вызывать и так нельзя. Он вызовется сам. Вызовется потому, что объект (тот-самый прокси объект, который участвует только на промежуточном этапе) вышел из области видимости.
Тогда всё ещё запутанее.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
 
using namespace std;
 
class A
{
public:
    A()           { cout << "I'm default ctor\n"; }
    ~A()          { cout << "I'm destructor\n"; }
};
 
A g () {
 A a;
 return a;
} 
 
int main() {
    g ();
    getchar();
    return 0;
}
Включаем оптимизацию, КК не вызывается. Но деструктор вызывается. Почему? Из зоны видимости он не вышел- из зоны видимости не g, но конечно же main, ибо как я уже дал понять, он создался сразу в main и следовательно он автоматичен именно для main. Да, так вот. Функция main не закончилась, а объект, определённый в ней умер.

Вот это путаница. И не по названию, а по сути. И если она появилась вследствие оптимизации, то грош последней цена. Вот, наверное, потому я и отключаю её.
0
Эксперт С++
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
27.06.2011, 01:57 22
Цитата Сообщение от kravam Посмотреть сообщение
Включаем оптимизацию, КК не вызывается. Но деструктор вызывается. Почему? Из зоны видимости он не вышел- из зоны видимости не g, но конечно же main, ибо как я уже дал понять, он создался сразу в main и следовательно он автоматичен именно для main.
В функции main нет никакого объекта, который бы существовал до конца работы программы.. Конструктор копирования в данном случае не вызывается потому, что копировать некуда. Временный же объект, который является результатом вызова этой функции (и в который проискодит копирование при отключённой оптимизации копирования) имеет областью видимости вовсе не main, а лишь ту точку, где его можно было бы использовать при желании, то есть в месте вызова функции. Вот там он сразу же и удаляется. Нет никакой путаницы. Отключать оптимизацию неразумно. Иначе лучше вообще забыть и про C++ и даже про C и программировать сразу на ассемблере.

Добавлено через 1 минуту
Цитата Сообщение от kravam Посмотреть сообщение
Да, так вот. Функция main не закончилась, а объект, определённый в ней умер.
Этот объект был определён не в функции main. И оттого, что он умер, никому хуже не стало. И не могло стать.
0
187 / 174 / 18
Регистрация: 22.03.2010
Сообщений: 612
27.06.2011, 04:38 23
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
A g () {
 A a;
012015D7  lea         ecx,[ebp-14h] 
012015DA  call        A::A (120111Dh) 
012015DF  mov         dword ptr [ebp-4],1 
 return a;
012015E6  lea         eax,[ebp-14h] 
012015E9  push        eax  
012015EA  mov         ecx,dword ptr [ebp+8] 
012015ED  call        A::A (1201267h) 
012015F2  mov         ecx,dword ptr [ebp-0E0h] 
012015F8  or          ecx,1 
012015FB  mov         dword ptr [ebp-0E0h],ecx 
01201601  mov         byte ptr [ebp-4],0 
01201605  lea         ecx,[ebp-14h] 
01201608  call        A::~A (1201145h) 
0120160D  mov         eax,dword ptr [ebp+8] 
} 
...
0120163F  ret
012015DA вызывается конструктор автоматического объекта
012015ED вызывается конструктор копирования*
01201608 вызывается деструктор для автоматического объекта
теперь в стеке находится объект А и управление возращается в main

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main() {
    g ();
012017DE  lea         eax,[ebp-0C8h] 
012017E4  push        eax  
012017E5  call        g (12010FAh) 
012017EA  add         esp,4 
012017ED  lea         ecx,[ebp-0C8h] 
012017F3  call        A::~A (1201145h) 
    getchar();
012017F8  mov         esi,esp 
012017FA  call        dword ptr [__imp__getchar (120A3DCh)] 
01201800  cmp         esi,esp 
01201802  call        @ILT+415(__RTC_CheckEsp) (12011A4h) 
    return 0;
01201807  xor         eax,eax 
}
тут хитроумный мелкомягкий компилятор видимо заметил, что управление над тем объектом A утеряно и удалил его до выхода из области видимости, что впринципе логично. Видимо kravam про этот автоматический объект в main говорил?

* Я изменил программу, добавив явный конструктор копирования
0
Делаю внезапно и красиво
Эксперт С++
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
27.06.2011, 06:29 24
Цитата Сообщение от kravam Посмотреть сообщение
Вот, наверное, потому я и отключаю её.
Ну с чего ты взял, что в namespace main'a хоть что-то создавалось? Ты вызвал функцию, в ней создался объект, при выходе из функции он уничтожился. Компилятор понимает, что объект А после завершения функции не используется, поэтому не копирует его. А ты этого не понимаешь, поэтому отключаешь оптимизацию. Что я могу ещё сказать - молодец!
1
187 / 174 / 18
Регистрация: 22.03.2010
Сообщений: 612
27.06.2011, 07:33 25
В дебаг версии VS 2008 копирует, потом уничтожает а. В коде мейн уничтожает копию. В релиз версии он тупо выводит строки cout-ом, никаких объектов А, копий и деструкторов...

mingw дебаг версии действительно не копирует даже
0
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
27.06.2011, 16:26  [ТС] 26
Цитата Сообщение от Deviaphan Посмотреть сообщение
Ну с чего ты взял, что в namespace main'a хоть что-то создавалось? Ты вызвал функцию, в ней создался объект, при выходе из функции он уничтожился. Компилятор понимает, что объект А после завершения функции не используется, поэтому не копирует его. А ты этого не понимаешь, поэтому отключаешь оптимизацию. Что я могу ещё сказать - молодец!
Не путай меня и не лги. Я нигде не вопрошал- почему КК не вызывается, если объект не возвращается? Потому и не вызывается, что как ты сам сказал "после завершения функции не используется", это я и без тебя знаю.
0
Делаю внезапно и красиво
Эксперт С++
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
27.06.2011, 16:28 27
Да ты чо? А это что?
Цитата Сообщение от kravam Посмотреть сообщение
Почему? Из зоны видимости он не вышел- из зоны видимости не g, но конечно же main, ибо как я уже дал понять, он создался сразу в main и следовательно он автоматичен именно для main. Да, так вот. Функция main не закончилась, а объект, определённый в ней умер.
И где я лгу?
0
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
27.06.2011, 16:45  [ТС] 28
Алё, а при чём тут КК? Я спрашивал, почему объект, автоматичный для main, умер, а функция не закончилась ещё pito211 сказал, что "управление над тем объектом A утеряно и удалил его до выхода из области видимости, что впринципе логично"

А где в этой цитате спрашивал, почем не вызывается КК... и так далее?

Добавлено через 11 минут
pito211,ну да, я это и имел ввиду.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
 
using namespace std;
 
class A
{
public:
    A()           { cout << "I'm default ctor\n"; }
    ~A()          { cout << "I'm destructor\n"; }
};
 
A g () {
 A a;
 return a;
} 
 
int main() {
    g ();
    getchar();
    return 0;
}
Жаль, очень жаль, что в книгах написано одно, а на практике друое.
0
2300 / 1218 / 246
Регистрация: 16.03.2008
Сообщений: 5,818
Записей в блоге: 2
27.06.2011, 16:54 29
Как все странно.... Объект класса nemo_ должен удаляться объектом класса xx. Разве что за исключением каких то специализированных случаев когда объект класса xx - всего лишь генератор для объектов класса nemo_. Во втором случае позаботиться об удалении объекта должен тот кто его заказал. Ваш случай похож и в данной реализации вы обязаны освободить память в main (не хотите - переделывайте класс xx в соответствии с условием задачи)

Если же первый случай. В каком методе класса xx будет удаляться объект класса nemo_ неважно. (в т.ч и в деструкторе и в конструкторе). Но объект класса хх должен хранить указатель на объект класса nemo_

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

Добавлено через 6 минут
А кажеться дошло о чем вы. Я не совсем в тему ответил похоже
0
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
27.06.2011, 17:12  [ТС] 30
Цитата Сообщение от voral Посмотреть сообщение
Разве что за исключением каких то специализированных случаев когда объект класса xx - всего лишь генератор для объектов класса nemo_.
примерно так, nemo_ на самом деле вложен для в xx и я переопределяю [][]

Ну в общем вывод такой: передаёшь ссыль- позаботься о delete; да всё бы ничё, но её только в main и вызывать; но тут случай, что и не видно, что это ссыль:

matrix_ []
[]

Ладно, остаётся только передавать объект. Как уж я подумаю. Всем спасибо, извините, кого задел.
0
187 / 174 / 18
Регистрация: 22.03.2010
Сообщений: 612
27.06.2011, 17:20 31
странные у тебя запросы(по поводу самого первого листинга). Думаю в полевых условиях такие вещи впринципе городить не придётся
1
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
27.06.2011, 17:36  [ТС] 32
Код сырой, можешь сразу посмотреть main
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <typeinfo>
#include <time.h>
 
template <class T>
class matrix {
 public:
 
  //Кнструтор по умолчанию создаёт матрицу из 2-х строк и одного столбца; ничем не инициализирует
  matrix () {srand (time(0));kol_vo_strok= 2; kol_vo_stolb= 1;};        
 
  //Конструктор просто создаёт матрицу, выделяет место под строи и столбцы, но не инициализирует их
  //В деструкторе, понятно, эта память освободится
  matrix (int x, int y):kol_vo_strok(x), kol_vo_stolb(y) {
   srand (time(0));
   p= new T* [x];
   for (int i= 0; i< x; i++) {
    p[i]= new T [y];
   }
  };        
 
 
  //А это деструктор, освобождает на хер всю занятую память
  ~matrix () {
   for (int i= 0; i< kol_vo_strok; i++)
    delete [] p[i];
    delete [] p;
   };        
 
  //Инициализация матрицы рандомно значениями от x до y влючительно
  //если значения типа double, то тоже будет всё нормально, после запятой будет два знака
  void init_rand (int x, int y) {
   double temp;
   for (int i= 0; i< get_kol_vo_strok(); i++) {
    for (int j = 0; j< get_kol_vo_stolb(); j++) {
     p[i][j]= rand()%(y- x+ 1)+ x;
     if (typeid(p[i][j])== typeid (temp)) {
      if (p[i][j]!= y) {
       p[i][j]+= (T)rand()/(RAND_MAX+1);;
      }
     }
    }
   }
  }
 
 
  //Это вот вывод матрицы
  void vivod () {
   double temp;
   for (int i= 0; i< get_kol_vo_strok(); i++) {
    for (int j = 0; j< get_kol_vo_stolb(); j++) {
     if (typeid(p[i][j])== typeid (temp))
      printf ("%.2f ", (double)p[i][j]);  
     else
      printf ("%3d ", p[i][j]);  
    }
    printf ("\n");
   }
  }
 
 
 
  //Устанавливает количество строк
  void set_kol_vo_strok (T x) {kol_vo_strok= x;};
  //... и количество столбцов
  void set_kol_vo_stolb (T x) {kol_vo_stolb= x;}
 
 
  //Возвращаает количество строк
  int get_kol_vo_strok () {return kol_vo_strok;};
  //... и количество столбцов
  int get_kol_vo_stolb () {return kol_vo_stolb;}
 
  
  //Перегрузка операторов
  //Это перегрузка оператора []; работает пока но этого мало, надо чтобы была перегрузка [][]  
 
  class nemo {
   public:
    T* k;   
    T& operator[](int nomer_stolbtsa) {
     return (k[nomer_stolbtsa]);
    };
  };
  
  //А вот из этой функции возвращается объект класса nemo. 
  //ПОка возвращается ссыль, но я буду переделывать, чтобы возвращался объект.
  nemo& operator[](int nomer_stroki) {
   nemo* ne= new nemo [1];
   ne->k= (T*)(p[nomer_stroki]); 
   return *ne;
  };
  
 
 
 
 private:
 
  //Количество строк, количество столбцов
  int kol_vo_strok;         
  int kol_vo_stolb;         
 
 
// public:
  //Динамический мссив из указателей на указатели на T
  T**p;
 
 
};
 
 
int main () {
 
 matrix<int> y (6, 7);
 y.init_rand (1, 100);
 y.vivod();
 printf ("\n");  
 
 //Благодаря моей дури, эта херь корректна:
 printf ("%d\n", y[3][4]);  
 y[3][4]= 99;
 
 y.vivod();
 printf ("\n");  
 
 getchar (); 
 
}
0
Каратель
Эксперт С++
6609 / 4028 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
27.06.2011, 17:41 33
Цитата Сообщение от kravam Посмотреть сообщение
надо чтобы была перегрузка [][]
для этого делается класс вектор(в котором перегружен оператор []), на базе которого делается класс матрицы(в котором тоже перегружен оператор [])
0
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
27.06.2011, 17:46 34
kravam, есть какая-то магия, какие-то дикие запросы на то, чтобы в классе matrix хранить именно двойной указатель, а не массив объектов nemo? Потому что пока это выглядит как извращение и хреновое проектирование. Храни вы массив строк, то вы бы просто из operator[] матрицы возвращали ссылку на строку, а из operator[] строки возвращали элемент строки. Недавно эта тема разжёвывалась же.
Вот.
0
187 / 174 / 18
Регистрация: 22.03.2010
Сообщений: 612
27.06.2011, 17:52 35
зачем интересно нужен конструктор по умолчанию, если он не рабочий спрячь его в приват

Добавлено через 4 минуты
лучше перегружать оператор(), а то так ты получается даёшь пользователю поиграться с указателями matrix[]. В терминологии не силён но помоему тут нарушается инкапсуляция или что-то типо того. Но точно что-то из принципов ООП нарушается

double temp; в 35 строке неиспользуемая переменная, точнее она только в typeid используется, короче выкинуть её

и вобще это всё жуткий быдлокод, весь обплевался пока читал
1
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
27.06.2011, 18:46  [ТС] 36
Советов я ничьих не спрашивал. Это кстати. Всё, что вы сказали- лишнее, могли бы не говорить. Я слишком ответственно отношусь к любому своему код, чтобы не отвечать за каждую строчку

Специально для тех, кто не увидел: это класс шаблонный, предполагается матрица из ЛЮБЫХ авторских переменных

C++
1
2
3
struct tip {
 //куча полей
}
Именно поэтому
C++
1
T** p;
А иначе, silent_1991, ума хранить массив строк у меня хватило бы. Скажи ещё, что не веришь мне?

И да, для каждого авторского класса мне придётся переопределять функции, например vivod и не надо мне об этом говорить.

"зачем интересно нужен конструктор по умолчанию, если он не рабочий спрячь его в приват"
Он рабочий и он нужен. Как нужен конструктор пустой строки или пустого вектора, ОК?

"лучше перегружать оператор(), а то так ты получается даёшь пользователю поиграться с указателями matrix[]" Это ты что предлагаешь?
matrix () (); matrix () [] или matrix [] ()?

Конгениально, чё могу сказать

"В терминологии не силён но помоему тут нарушается инкапсуляция или что-то типо того. Но точно что-то из принципов ООП нарушается"" тьфу

"и вобще это всё жуткий быдлокод, весь обплевался пока читал " тебя никто об этом не просил, надо было- посмотрел бы только то, что я сказал посмотреть, сказано было- код сырой.
0
Эксперт С++
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
27.06.2011, 18:49 37
Хочется только немного слов сказать в защиту прокси-объектов. Никакие принципы ООП они при правильной реализации не нарушают. И иногда это единственный из удобных способов получить желаемое. В данном случае не единственный, но вполне возможный.
1
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
27.06.2011, 18:50 38
kravam, во-первых, я не давал повода так со мной разговаривать. Во-вторых, про строки (string или char*) речи не шло. И что, что класс шаблонный? Гляньте код по ссылке, сделайте классы Row и Matrix шаблонными и живите счастливо.
0
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
27.06.2011, 18:51  [ТС] 39
В данном случае, например.
И вообще скропайте перегрузку оператора [][] по-другому, предполагая, что элемент матрицы- элемент любого типа, тогда и будете базлать. Пока же всем вашим замечаниям в базарный день красная цена копейка.
0
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
27.06.2011, 18:55 40
Цитата Сообщение от kravam Посмотреть сообщение
И вообще скропайте перегрузку оператора [][] по-другому, предполагая, что элемент матрицы- элемент любого типа
Да пожалуйста, что мне, жалко, что-ли?

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include <iostream>
 
template< typename T >
class Row
{
public:
    Row(size_t size = 1):
    m_size(size),
    m_row(new T [m_size])
    {
        for (size_t i = 0; i < m_size; ++i)
            m_row[i] = 0.0;
    }
 
    Row(const Row &source):
    m_size(source.m_size),
    m_row(new T [m_size])
    {
        for (size_t i = 0; i < m_size; ++i)
            m_row[i] = source.m_row[i];
    }
 
    ~Row()
    {
        delete [] m_row;
    }
 
    void resize(size_t new_size)
    {
        double *new_row = new T [new_size];
 
        for (size_t i = 0; i < m_size; ++i)
            new_row[i] = m_row[i];
 
        for (size_t i = m_size; i < new_size; ++i)
            new_row[i] = 0.0;
        
        delete [] m_row;
 
        m_row = new_row;
        m_size = new_size;
    }
 
    T &operator[](size_t index)
    {
        return m_row[index];
    }
 
    const T &operator[](size_t index) const
    {
        return m_row[index];
    }
 
private:
    size_t m_size;
    T *m_row;
};
 
template< typename T >
class Matrix
{
public:
    Matrix(size_t rows = 1, size_t cols = 1):
    m_rows(rows),
    m_matrix(new Row< T > [m_rows])
    {
        for (size_t i = 0; i < m_rows; ++i)
            m_matrix[i].resize(cols);
    }
 
    ~Matrix()
    {
        delete [] m_matrix;
    }
 
    Row< T > &operator[](size_t index)
    {
        return m_matrix[index];
    }
 
    const Row< T > &operator[](size_t index)const
    {
        return m_matrix[index];
    }
 
private:
    size_t m_rows;
    Row< T > *m_matrix;
};
 
int main()
{
    const size_t rows = 2;
    const size_t cols = 2;
 
    Matrix< double > m(rows, cols);
 
    for (size_t i = 0; i < rows; ++i)
        for (size_t j = 0; j < cols; ++j)
            m[i][j] = i + j;
 
    for (size_t i = 0; i < rows; ++i)
    {
        for (size_t j = 0; j < cols; ++j)
            std::cout << m[i][j] << "  ";
 
        std::cout << std::endl;
    }
 
    return 0;
}
0
27.06.2011, 18:55
Ответ Создать тему
Опции темы

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