как работает delete []ptr?
От: epflorov Россия www.epflorov.hotbox.ru
Дата: 15.07.02 12:24
Оценка:
Здравствуйте.

Тема http://www.rsdn.ru/forum/message.asp?mid=72857
Автор:
Дата: 15.07.02
напомнила мне о следующем.

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

...
int i = 100;
foo *ptr = new foo[i];
...
delete []ptr; //откуда здесь становится известно о количестве элементов в массиве?


Евгений Флоров
Евгений Флоров
Re: как работает delete []ptr?
От: Alik Украина  
Дата: 15.07.02 12:29
Оценка: 1 (1)
Здравствуйте epflorov, Вы писали:

E>Здравствуйте.


E>Тема http://www.rsdn.ru/forum/message.asp?mid=72857
Автор:
Дата: 15.07.02
напомнила мне о следующем.


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

E>то есть

E>
E>...
E>int i = 100;
E>foo *ptr = new foo[i];
E>...
E>delete []ptr; //откуда здесь становится известно о количестве элементов в массиве?
E>


Читаем учебники (т.е. Страуструпа)
"Стандартная реализация new выделяет памяти немного больше, чем потребовалось бы для статического объекта. Как правило, используется одно дополнительное слово для хранения размера объекта".
С уважением. Алик.
Re: как работает delete []ptr?
От: Gi Россия  
Дата: 15.07.02 12:31
Оценка: 1 (1)
Здравствуйте epflorov, Вы писали:

E>Здравствуйте.


E>Тема http://www.rsdn.ru/forum/message.asp?mid=72857
Автор:
Дата: 15.07.02
напомнила мне о следующем.


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

E>то есть

E>
E>...
E>int i = 100;
E>foo *ptr = new foo[i];
E>...
E>delete []ptr; //откуда здесь становится известно о количестве элементов в массиве?
E>


E>Евгений Флоров


кол-во элементов = размер выделенной памяти/sizeof(foo), и то и другое компилеру известно.
Re: как работает delete []ptr?
От: Kaa Украина http://blog.meta.ua/users/kaa/
Дата: 15.07.02 12:32
Оценка: 1 (1)
Здравствуйте epflorov, Вы писали:

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

E>то есть

E>
E>...
E>int i = 100;
E>foo *ptr = new foo[i];
E>...
E>delete []ptr; //откуда здесь становится известно о количестве элементов в массиве?
E>


Проблема то вся в том и есть, что мы — не компилятор. Мы не знаем, а он знает. А хранит он это в некотором заголовке к выделенной памяти, т.е. выделяется на самом деле не n байт, а n + размер заголовка, и туда складывается инфа о таких вещах, как размер выделяемого блока, и, возможно, еще что-то. Таким образом, образуется некоторый overhead, зато информация присутствует и доступна в любой момент.
Алексей Кирдин
Re: как работает delete []ptr?
От: Койнов Дмитрий  
Дата: 15.07.02 12:34
Оценка: -4
Здравствуйте epflorov, Вы писали:

E>Здравствуйте.


E>Тема http://www.rsdn.ru/forum/message.asp?mid=72857
Автор:
Дата: 15.07.02
напомнила мне о следующем.


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

E>то есть

E>
E>...
E>int i = 100;
E>foo *ptr = new foo[i];
E>...
E>delete []ptr; //откуда здесь становится известно о количестве элементов в массиве?
E>

Ниоткуда...

В данном случае было бы неплохо сделать так:

E>...
E>int i = 100;
E>foo *ptr = new foo[i];
E>...
for(int j=0; j<i; j++)
delete(ptr[j])
Re[2]: как работает delete []ptr?
От: Alik Украина  
Дата: 15.07.02 12:37
Оценка:
Здравствуйте Койнов Дмитрий, Вы писали:

КД>Здравствуйте epflorov, Вы писали:


E>>Здравствуйте.


E>>Тема http://www.rsdn.ru/forum/message.asp?mid=72857
Автор:
Дата: 15.07.02
напомнила мне о следующем.


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

E>>то есть

E>>
E>>...
E>>int i = 100;
E>>foo *ptr = new foo[i];
E>>...
E>>delete []ptr; //откуда здесь становится известно о количестве элементов в массиве?
E>>

КД>Ниоткуда...

КД>В данном случае было бы неплохо сделать так:


КД>
E>>...
E>>int i = 100;
E>>foo *ptr = new foo[i];
E>>...
КД>for(int j=0; j<i; j++)
КД>delete(ptr[j])
КД>


Хммм... Рискну не согласиться.
Насколько я знаю, вполне корректный код. Т.е. деструкторы вызовутся для всех элементов массива. В этом и суть delete[].
С уважением. Алик.
Re[3]: как работает delete []ptr?
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 15.07.02 12:42
Оценка: -1 :)
Здравствуйте Alik, Вы писали:

A>Здравствуйте Койнов Дмитрий, Вы писали:


КД>>Здравствуйте epflorov, Вы писали:


E>>>Здравствуйте.


E>>>Тема http://www.rsdn.ru/forum/message.asp?mid=72857
Автор:
Дата: 15.07.02
напомнила мне о следующем.


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

E>>>то есть

E>>>
E>>>...
E>>>int i = 100;
E>>>foo *ptr = new foo[i];
E>>>...
E>>>delete []ptr; //откуда здесь становится известно о количестве элементов в массиве?
E>>>

КД>>Ниоткуда...

КД>>В данном случае было бы неплохо сделать так:


КД>>
E>>>...
E>>>int i = 100;
E>>>foo *ptr = new foo[i];
E>>>...
КД>>for(int j=0; j<i; j++)
КД>>delete(ptr[j])
КД>>


A>Хммм... Рискну не согласиться.

A>Насколько я знаю, вполне корректный код. Т.е. деструкторы вызовутся для всех элементов массива. В этом и суть delete[].

Дополняя предыдущего оратора (Alik):


В этом и суть delete[]. — для встроенных типов данных... Для определенных вами типов (классов, структур), выделяемых "на куче", поведение delete[] может быть весьма непредсказыемым...





CMyClass* cPtr[20];

for(int i=0;i<20;i++)
  cPtr[i] = new CMyClass;

delete [] cPtr; // так низзя :-))
Re[2]: изучайте матчасть, молодой человек (-)
От: Аноним  
Дата: 15.07.02 12:45
Оценка: :)
Re[2]: как работает delete []ptr?
От: Mish Россия  
Дата: 15.07.02 12:46
Оценка:
Здравствуйте Койнов Дмитрий, Вы писали:

КД>Здравствуйте epflorov, Вы писали:



КД>Ниоткуда...


КД>В данном случае было бы неплохо сделать так:


КД>
E>>...
E>>int i = 100;
E>>foo *ptr = new foo[i];
E>>...
КД>for(int j=0; j<i; j++)
КД>delete(ptr[j])
КД>


Не стОит так делать. Программа упадёт непременно.
Re[3]: как работает delete []ptr?
От: Flea  
Дата: 15.07.02 12:54
Оценка:
Здравствуйте Mish, Вы писали:

M>Здравствуйте Койнов Дмитрий, Вы писали:


КД>>Здравствуйте epflorov, Вы писали:



КД>>Ниоткуда...


КД>>В данном случае было бы неплохо сделать так:


КД>>
E>>>...
E>>>int i = 100;
E>>>foo *ptr = new foo[i];
E>>>...
КД>>for(int j=0; j<i; j++)
КД>>delete(ptr[j])
КД>>


M>Не стОит так делать. Программа упадёт непременно.

Не будет ли Вам сложно объяснить, почему?


Re[4]: как работает delete []ptr?
От: Gi Россия  
Дата: 15.07.02 12:55
Оценка:
Здравствуйте Flamer, Вы писали:

F>Здравствуйте Alik, Вы писали:


A>>Здравствуйте Койнов Дмитрий, Вы писали:


КД>>>Здравствуйте epflorov, Вы писали:


E>>>>Здравствуйте.


E>>>>Тема http://www.rsdn.ru/forum/message.asp?mid=72857
Автор:
Дата: 15.07.02
напомнила мне о следующем.


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

E>>>>то есть

E>>>>
E>>>>...
E>>>>int i = 100;
E>>>>foo *ptr = new foo[i];
E>>>>...
E>>>>delete []ptr; //откуда здесь становится известно о количестве элементов в массиве?
E>>>>

КД>>>Ниоткуда...

КД>>>В данном случае было бы неплохо сделать так:


КД>>>
E>>>>...
E>>>>int i = 100;
E>>>>foo *ptr = new foo[i];
E>>>>...
КД>>>for(int j=0; j<i; j++)
КД>>>delete(ptr[j])
КД>>>


A>>Хммм... Рискну не согласиться.

A>>Насколько я знаю, вполне корректный код. Т.е. деструкторы вызовутся для всех элементов массива. В этом и суть delete[].

F>Дополняя предыдущего оратора (Alik):



F>В этом и суть delete[]. — для встроенных типов данных... Для определенных вами типов (классов, структур), выделяемых "на куче", поведение delete[] может быть весьма непредсказыемым...





F>

F>CMyClass* cPtr[20];

F>for(int i=0;i<20;i++)
F>  cPtr[i] = new CMyClass;

F>delete [] cPtr; // так низзя :-))

F>


так здесь же удаляется память на стеке, причём тут delete[]?
Re[4]: как работает delete []ptr?
От: Bell Россия  
Дата: 15.07.02 12:55
Оценка:
Здравствуйте Flamer, Вы писали:


F>В этом и суть delete[]. — для встроенных типов данных... Для определенных вами типов (классов, структур), выделяемых "на куче", поведение delete[] может быть весьма непредсказыемым...





F>

F>CMyClass* cPtr[20];

F>for(int i=0;i<20;i++)
F>  cPtr[i] = new CMyClass;

F>delete [] cPtr; // так низзя :-))

F>


Поведение оператора delete [] предсказуемо для любых типов данных - для каждого элемента массива будет вызван деструктор. Исключение составляют встроенные типы, которые не имеют деструкторов в общем понимании.
В твоем примере массив содержит указатели, а указатели есть встроенный тип, так что delete [] здесь абсолютно не при чем.И код
CMyClass* cPtr = new CMyClass[20];
...
delete [] cPtr;


абсолютно корректен, т.е. для каждого элемента cPtr бкдет вызван деструктор.
Любите книгу — источник знаний (с) М.Горький
Re[4]: как работает delete []ptr?
От: epflorov Россия www.epflorov.hotbox.ru
Дата: 15.07.02 12:57
Оценка:
Здравствуйте Flamer, Вы писали:

F>В этом и суть delete[]. — для встроенных типов данных... Для определенных вами типов (классов, структур), выделяемых "на куче", поведение delete[] может быть весьма непредсказыемым...


F>

F>CMyClass* cPtr[20];

F>for(int i=0;i<20;i++)
F>  cPtr[i] = new CMyClass;

F>delete [] cPtr; // так низзя :-))

F>


Поясните пожалуйста.
Вы пытаетесь удалить массив выделенный в стеке?
Или Вы имели ввиду:
CMyClass* cPtr = new CMyClass[20];
for(int i=0;i<20;i++)
  cPtr[i] = new CMyClass;
delete [] cPtr; // и здесь мы теряем все указатели?


Евгений Флоров.
Евгений Флоров
Re[4]: как работает delete []ptr?
От: Gi Россия  
Дата: 15.07.02 13:00
Оценка:
Здравствуйте Flea, Вы писали:

F>Здравствуйте Mish, Вы писали:


M>>Здравствуйте Койнов Дмитрий, Вы писали:


КД>>>Здравствуйте epflorov, Вы писали:



КД>>>Ниоткуда...


КД>>>В данном случае было бы неплохо сделать так:


КД>>>
E>>>>...
E>>>>int i = 100;
E>>>>foo *ptr = new foo[i];
E>>>>...
КД>>>for(int j=0; j<i; j++)
КД>>>delete(ptr[j])
КД>>>


M>>Не стОит так делать. Программа упадёт непременно.

F>Не будет ли Вам сложно объяснить, почему?


F>


Потомучто ptr[j] это не указатель, а объект типа foo.
Re[4]: как работает delete []ptr?
От: Mish Россия  
Дата: 15.07.02 13:15
Оценка:
Здравствуйте Flea, Вы писали:


КД>>>
E>>>>...
E>>>>int i = 100;
E>>>>foo *ptr = new foo[i];
E>>>>...
КД>>>for(int j=0; j<i; j++)
КД>>>delete(ptr[j])
КД>>>


M>>Не стОит так делать. Программа упадёт непременно.

F>Не будет ли Вам сложно объяснить, почему?

Фрагмент
foo *ptr = new foo[i];


выделяет память для хранения i элементов массива, а не i блоков. В начале этого фрагмента лежит какая-то служебная информация о выделенном блоке, которая используется при удаления блока (например указатель на след блок и размер блока, необходимый для расчёта кол-ва элементов и соответственно число вызовов деструкторов). Если подсунуть опертору delete некий адрес из середины блока, то он скорее всего что-нибудь попортит, когда будет удалять его из списка блоков.

Вот задумался, а можно ли придумать хитрую реализацию, для которой бы приведённый фрагмент работал бы коректно?
Надо тщательно смотреть стандарты, чтобы ответить на этот вопрос, но скорее всего нет. Иначе надо запихивать в этот блок дополнительную информацию, что видится мне идеологически неправильным.
Re[5]: как работает delete []ptr?
От: Mish Россия  
Дата: 15.07.02 13:19
Оценка:
КД>>>>
E>>>>>...
E>>>>>int i = 100;
E>>>>>foo *ptr = new foo[i];
E>>>>>...
КД>>>>for(int j=0; j<i; j++)
КД>>>>delete(ptr[j])
КД>>>>


и как правильно заметил Gi, ptr[i] — это объект, а не указатель, Я имел в виду, что delete(&ptr[j]) неправильно, потому что порушит цепочку блоков памяти.
Re: как работает delete []ptr?
От: Андрей Тарасевич Беларусь  
Дата: 15.07.02 15:36
Оценка:
Здравствуйте epflorov, Вы писали:

E>Тема http://www.rsdn.ru/forum/message.asp?mid=72857
Автор:
Дата: 15.07.02
напомнила мне о следующем.


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


Не понимаю вопроса. Мы действительно не можем знать размер массива. А компилятор — может. Деструкторы-то вызывает компилятор, а не мы.
Best regards,
Андрей Тарасевич
Re[5]: как работает delete []ptr?
От: Аноним  
Дата: 15.07.02 15:59
Оценка:
Здравствуйте Mish, Вы писали:

E>>>>>...
E>>>>>int i = 100;
E>>>>>foo *ptr = new foo[i];
E>>>>>...
КД>>>>for(int j=0; j<i; j++)
КД>>>>delete(ptr[j])


M>Вот задумался, а можно ли придумать хитрую реализацию, для которой бы приведённый фрагмент работал бы коректно?


Конечно, можно. Для этого достаточно перегрузить для класса 'foo' оператор 'new[]', оператор приведения к указателю на какой-либо тип и для этого типа оператор 'delete'. И еще — поставить ';' после 'delete(ptr[j])'.
Re: как работает delete []ptr?
От: YuriS Германия www.yuris.de
Дата: 15.07.02 18:19
Оценка: 3 (1)
Привет Всем!

Предлагаю всем оглянуться "Назад в будущее" и почитать сдесь:
http://www.rsdn.ru/forum/message.asp?mid=24931
Автор: Constructor
Дата: 29.01.02


Я думаю, что тема довольно-таки хорошо уже обсуждалась
Re[2]: как работает delete []ptr?
От: epflorov Россия www.epflorov.hotbox.ru
Дата: 15.07.02 18:27
Оценка:
Здравствуйте YuriS, Вы писали:

YS>Привет Всем!


YS>Предлагаю всем оглянуться "Назад в будущее" и почитать сдесь:

YS>http://www.rsdn.ru/forum/message.asp?mid=24931
Автор: Constructor
Дата: 29.01.02


YS>Я думаю, что тема довольно-таки хорошо уже обсуждалась


Спасибо. Если бы у меня работал поиск, то я обязательно сам бы поискал.
Еще раз спасибо.

Евгений Флоров.
Евгений Флоров
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.