Вопрос :
1) Я выделяю память например так:
char* pChar = new char[10];
при вызове "delete pChar" удалится вся память ?
2) Каковы различия в вызовах "delete [] pChar" и "delete pChar" ?
Re: new для выделения памяти под массив ( new char[ 10 ] )
Здравствуйте, ZZTop, Вы писали:
ZZT>Вопрос : ZZT>1) Я выделяю память например так: ZZT>char* pChar = new char[10]; ZZT>при вызове "delete pChar" удалится вся память ? ZZT>2) Каковы различия в вызовах "delete [] pChar" и "delete pChar" ?
1. Правильно в этом случае делать delete[].
2. Различия проявляются в случае, если объекты имеют нетривиальные деструкторы.
Re: new для выделения памяти под массив ( new char[ 10 ] )
От:
Аноним
Дата:
24.09.03 16:40
Оценка:
Здравствуйте, ZZTop, Вы писали:
ZZT>1) Я выделяю память например так: ZZT>char* pChar = new char[10]; ZZT>при вызове "delete pChar" удалится вся память ?
В некоторых (возможно даже, в большинстве) средах разработки тебе может повезти и этот вызов будет отработан так же, как и правильный:
delete[] pChar;
Но вообще это вилами на воде писано.
ZZT>2) Каковы различия в вызовах "delete [] pChar" и "delete pChar" ?
Правило тривиально: память, выделенная посредством new, должна высвобождаться посредством delete; память, выделенная посредством new[], должна высвобождаться посредством delete[].
Различие между ними является необходимым при освобождении массивов объектов, обладающих деструкторами, т. к. необходимо обеспечить не только освобождение памяти, но и корректный вызов деструктора для каждого объекта. Для этого нужно иметь отличный от случая одиночного объекта формат разметки выделенного блока.
Re: new для выделения памяти под массив ( new char[ 10 ] )
Здравствуйте, ZZTop, Вы писали:
ZZT>Вопрос : ZZT>1) Я выделяю память например так: ZZT>char* pChar = new char[10]; ZZT>при вызове "delete pChar" удалится вся память ?
Вызов 'delete pChar' в данном случае приводит к неопределенному поведению. Для удаления объектов типа "массив" применяется 'delete[]' и только 'delete[]'
ZZT>2) Каковы различия в вызовах "delete [] pChar" и "delete pChar" ?
'delete[]' применяется для удаления объектов типа "массив". 'delete' применяется для удаления одиночных объектов.
Best regards,
Андрей Тарасевич
Re[2]: new для выделения памяти под массив ( new char[ 10 ]
Здравствуйте, Вадим Никулин, Вы писали:
ZZT>>Вопрос : ZZT>>1) Я выделяю память например так: ZZT>>char* pChar = new char[10]; ZZT>>при вызове "delete pChar" удалится вся память ? ZZT>>2) Каковы различия в вызовах "delete [] pChar" и "delete pChar" ?
ВН>1. Правильно в этом случае делать delete[].
ВН>2. Различия проявляются в случае, если объекты имеют нетривиальные деструкторы.
Совсем не обязательно только в этом случае. Механизмы 'new/delete' и 'new[]/delete[]' могут быть принципиально различными. Смешивание этих способов выделения/освобождения памяти потенциально ведет к неопределенному поведению независимо от характеристик деструктров объектов.
Best regards,
Андрей Тарасевич
Re[3]: new для выделения памяти под массив ( new char[ 10 ]
От:
Аноним
Дата:
25.09.03 06:35
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:
АТ>Совсем не обязательно только в этом случае. Механизмы 'new/delete' и 'new[]/delete[]' могут быть принципиально различными. Смешивание этих способов выделения/освобождения памяти потенциально ведет к неопределенному поведению независимо от характеристик деструктров объектов.
А delete[] знает о типе объектов?
например такое нормально?
char* pc = new[16];
long* pl = reinterpret_cast< long* >( pc );
delete[] pl;
а такое?
ClassA* pA = new ClassA[16];
ClassB* pB = reinterpret_cast< ClassB* >( pA );
delete[] pB;
А если выделить массив char, потом сделать placement new и освобождать память как массив объектов?
Будут корректно вызваны деструкторы объектов в массиве?
Re[4]: new для выделения памяти под массив ( new char[ 10 ]
Здравствуйте, Аноним, Вы писали:
А>А delete[] знает о типе объектов?
Он определяет, сколько освобождать памяти, не исходя из типа объекта, а используя некоторую инфу, ассоциированную с освобождаемым участком памяти. Деструктор, который вызовется, опреляется исходя из типа указателя. Запись delete[] говорит, что вызывать деструктор надо не у одного объекта, а у каждого из массива объектов.
А>например такое нормально? А>
А>char* pc = new[16];
А>long* pl = reinterpret_cast< long* >( pc );
А>delete[] pl;
А>
Вполне.
А> а такое? А>
А>ClassA* pA = new ClassA[16];
А>ClassB* pB = reinterpret_cast< ClassB* >( pA );
А>delete[] pB;
А>
Память освободится, однако вызовутся деструкторы ClassB.
Re[5]: new для выделения памяти под массив ( new char[ 10 ]
Здравствуйте, Аноним, Вы писали:
А>например такое нормально? А>
А>char* pc = new[16];
А>long* pl = reinterpret_cast< long* >( pc );
А>delete[] pl;
А>
Учитывая, что оба типа не обладают деструкторами, то плохого не будет. Но вообще говоря (если говорить о двух произвольных разных типах) такое использование delete[] приведёт к ошибке.
А> а такое? А>
А>ClassA* pA = new ClassA[16];
А>ClassB* pB = reinterpret_cast< ClassB* >( pA );
А>delete[] pB;
А>
Ошибка.
А>А если выделить массив char, потом сделать placement new и освобождать память как массив объектов? А>Будут корректно вызваны деструкторы объектов в массиве?
Пример:
class test
{
protected:
int x;
public:
test() {x = 1;}
~test() {x = 0;}
}
int main(char *, int)
{
test * lpTest = new test[4];
}
У оператора new будет запрошено 4*sizeof(test) + sizeof(int) = 4*4+4 = 20 байт
Почему? Потому что в начале массива используеться 4 байта для хранения его размера в элементах. А чтоб мы этого не заметили они фактически ДО возвращаемого нам указателя
delete[] и new[] в том виде в каком он работает (для VC6/7) можно описать так
template<class TYPE>
TYPE * New(unsigned int size)
{
int arraySize = size + sizeof(int);
TYPE * lpMemory = (TYPE *)(((unsigned int)malloc(arraySize)) + sizeof(int));
if (lpMemory == (- sizeof(int))) return NULL
for (unsigned int i = 0; i < size/sizeof(TYPE); i++)
{
(lpMemory + i)->TYPE();
}
return lpMemory;
}
template<class TYPE>
void Delete(TYPE * lpMemory)
{
int arraySize = *((int *)(((unsigned int)lpMemory) - sizeof(int)));
for (unsigned int i = 0; i < arraySize; i++)
{
(lpMemory + i)->~TYPE();
}
free(lpMemory);
}
Здравствуйте, adontz, Вы писали:
А>> например такое нормально? А>>
А>> char* pc = new[16];
А>> long* pl = reinterpret_cast< long* >( pc );
А>> delete[] pl;
А>>
a> Учитывая, что оба типа не обладают деструкторами, то плохого не будет.
Undefined behavior. Проявления зависят от реализации. Например, для char[] и для long[]
вполне могут резервироваться заголовки различного размера, что в приведенном примере приведет
к феерверку в связи с освобождением памяти не по тому адресу, по которому она выделялась.
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[6]: new для выделения памяти под массив ( new char[ 10 ]
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Undefined behavior. Проявления зависят от реализации. Например, для char[] и для long[] ПК>вполне могут резервироваться заголовки различного размера,
А зачем вообще заголовки типам без деструктора? С чего бы им создаваться? Нет я не спорю, что может по стандарту оно и Undefined но по жизни оно канкретна Defined
Здравствуйте, adontz, Вы писали:
ПК>> Undefined behavior. Проявления зависят от реализации. Например, для ПК>> char[] и для long[] вполне могут резервироваться заголовки ПК>> различного размера,
a> А зачем вообще заголовки типам без деструктора?
Например, для какой-нибудь диагностики границ массивов. Или потому что разработчики
компилятора не тратили время на оптимизацию заголовков для POD-типов etc.
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен