LINUX.ORG.RU

C++, 2-й вопрос.


0

0

Почему для ClassName* p = new ClassName(); рекомендуется вызывать «delete p;», а для «char *p = new char[1200];» рекомендуется вызывать «delete[] p;» ?

Я не понимаю потому, что рассуждаю, что в обоих случаях был выделен просто некий кусок «кучи». После первого new, правда, вызвался конструктор. Но ведь по сути, с точки зрения управления памятию, это просто два куска сплошного адресного пространства? Информация о них - адрес начала, размер. Почему разные операторы delete?

Я вас всех люблю, драгоценные мои.

Ибо выделяя память под класс ты выделяешь память под один экземпляр типа(класса), а во втором - под некоторое количество экземпляров. Для последнего случае и существует delete[].
Всё просто.

tia
()
Ответ на: комментарий от tia

Спасибо.

Честно говоря, так и думал.

char *p = new char [ 1024 ];

это по виду то же, что

TypeName *p = new TypeName [ 1024 ];


Ok. То есть, по задумке Страуструпа, delete[] - это 1024 вызовов деструктора? )

mriadus
() автор топика
Ответ на: комментарий от Booster

> Ерунду не пишите.

я не «пишу ерунду», а задаю вопрос. если нельзя, то какой смысл в delete[], если объявляется переменная-указатель на массив символов, то и удалятся она(ее данные) должна как переменная-указатель(как единое целое) => delete[] — просто необоснованное извращение

korvin_ ★★★★★
()
Ответ на: комментарий от korvin_

s/переменная-указатель на массив символов/переменная-указатель на данные типа (массив данных типа 'a)/

s/как единое целое/как единое целое — указатель на данные типа (массив данных типа 'a)/

korvin_ ★★★★★
()
Ответ на: комментарий от zJes

> А что, закономерный был вопрос :)

delete p[i], а delete[i] p не катит по той простой причине, что если делать по аналогии с new - то это был бы вызов деструкторов первых i объектов, что врядли кому-то надо и не имеет практического смысла

lester ★★★★
()
Ответ на: комментарий от lester

Ты прочитай первый его вывод :)

Ok. То есть, по задумке Страуструпа, delete[] - это 1024 вызовов деструктора? )

zJes ★★
()
Ответ на: комментарий от korvin_

>если нельзя, то какой смысл в delete[]
Для каждого объекта пришлось-бы хранить дополнительную информацию о типе памяти. Имеет ли это смысл если у нас много малых объектов?

Booster ★★
()
Ответ на: комментарий от Booster

> Для каждого объекта пришлось-бы хранить дополнительную информацию о типе памяти. Имеет ли это смысл если у нас много малых объектов?

с хера бы? только инфу о типе элементов массива.

korvin_ ★★★★★
()
Ответ на: комментарий от korvin_

>с хера бы? только инфу о типе элементов массива.
Зачем? Размер элемента компилятору известен. Ему не известно массив это или один элемент.

Booster ★★
()
Ответ на: комментарий от korvin_

>нет, спасибо, это не объясняет логики, которой руководствовался создатель языка

Побереги своё психическое здоровье - не ищи логику в C++

Led ★★★☆☆
()
Ответ на: комментарий от Booster

> Зачем? Размер элемента компилятору известен. Ему не известно массив это или один элемент.

как это неизвестен?

char *p = new char[1200];

квадратные скобочки здесь зачем тогда?

korvin_ ★★★★★
()
Ответ на: комментарий от Led

> Побереги своё психическое здоровье - не ищи логику в C++

я особо и не ищу, сугубо любопытство =)

korvin_ ★★★★★
()
Ответ на: комментарий от korvin_

>квадратные скобочки здесь зачем тогда?
А так что указатель может предаться чёрти куда и фиг уследишь, что было изначально.

Booster ★★
()
Ответ на: комментарий от korvin_

> то какой смысл в delete[]

Разница просто в new и new[]
Во втором случае автоматом аллокируется дополнительных 4(?) байта, в которых располагается размер выделенной области. delete [] смотрит эти 4 байта и высвобождает нужную область. Просто 2 разных метода аллокации.

zJes ★★
()
Ответ на: комментарий от Booster

> А так что указатель может предаться чёрти куда и фиг уследишь, что было изначально.

изначально был указатель на _тип_ «массив 1200 элементов типа char»

korvin_ ★★★★★
()
Ответ на: комментарий от korvin_

>изначально был указатель на _тип_ «массив 1200 элементов типа char»
Хи, изначально. Указатель на массив не отличается от указателя на один элемент.

Booster ★★
()
Ответ на: комментарий от korvin_

>ну в общем суть я понял, реализовать тип «массив» было не судьба, придумали костыль
А ты как думал, наследие Си.

Booster ★★
()
Ответ на: комментарий от Booster

> Хи, изначально. Указатель на массив не отличается от указателя на один элемент.

пардон, но, чем тогда отличаются char *a; от char *a[]; ?

но, впрочем Вы ответили:

А ты как думал, наследие Си.

значит [] — чисто для объявления псевдомассивов статичного размера?

korvin_ ★★★★★
()
Ответ на: комментарий от korvin_

Можно конечно объявить указатель на массив определённого размера, но это всё очень не надёжно, так как кастоваться может к чему угодно. Но в этом есть и гибкость.

Booster ★★
()
Ответ на: комментарий от korvin_

>> Зачем? Размер элемента компилятору известен. Ему не известно массив это или один элемент.

как это неизвестен?

char *p = new char[1200];

квадратные скобочки здесь зачем тогда?

А если подумать?

void foo(char *p) { delete [] p; }

а если сложнее

class A { virtual ~A() {} };

class B : public A {};

void foo(A *p) { delete p; // вызываем один деструктор А или B }

void bar(A *p) { delete [] p; // вызываем сколько надо деструкторов A или B. А ещё надо посчитать сколько их вызвать. И каких. }

в итоге foo явно быстрее bar. Но корректность на усмотрения программиста.

yatagarasu
()
Ответ на: комментарий от korvin_

>пардон, но, чем тогда отличаются char *a; от char *a[];

*a[] по сути тоже, что и **a

golodranez ★★★★
()

AFAIK в новой стандартной библиотеке можно будет задавать свою функцию разрушения.

Booster ★★
()
Ответ на: комментарий от Booster

в новой стандартной библиотеке можно будет задавать свою функцию разрушения

что такое функция разрушения? если перегруженный operator delete, то оно и в текущей вполне себе работает

jtootf ★★★★★
()
Ответ на: комментарий от jtootf

>что такое функция разрушения? если перегруженный operator delete, то оно и в текущей вполне себе работает
Перегрузить delete для Cи массива? Функция разрушения - функция в которую передаётся указатель на объект, когда он уничтожается смартпоинтером.

Booster ★★
()
Ответ на: комментарий от lester

Я понимаю, что глобальные операторы можно перегружать, но какой в этом толк в данном контексте? Надеюсь Вы не предлагаете заменить этим отсутствие унифицированного оператора удаления?

Booster ★★
()
Ответ на: комментарий от Booster

> Надеюсь Вы не предлагаете заменить этим отсутствие унифицированного оператора удаления?

у меня такой проблемы вообще нет - я new[] и delete[] не пользуюсь, если надо выделить область памяти - пользуюсь дедовскими malloc/free, для остальных случаев есть подходящие контейнеры, хотя да - таким способом можно избавится от необходимости delete[], кстати AFAIK в MSVC, например, разницы между delete и delete[] и так нет - по обоим операторам отрабатывает один и тот же код

lester ★★★★
()
Ответ на: комментарий от Booster

> Функция разрушения - функция в которую передаётся указатель на объект, когда он уничтожается смартпоинтером.

Чем это отличается от деструктора, который вызывается перед удалением памяти, занимаемой объектом?

m0rph ★★★★★
()
Ответ на: комментарий от lester

> кстати AFAIK в MSVC, например, разницы между delete и delete[] и так нет

Если не ошибаюсь, в MSVC оператор delete реализован как обертка над функцией free из libc. Т.е. delete вызывает деструкторы, а потом делает вызов free.

m0rph ★★★★★
()
Ответ на: комментарий от m0rph

>Чем это отличается от деструктора, который вызывается перед удалением памяти, занимаемой объектом?
Это не деструктор, а функция уничтожения захваченного смартпоинтером ресурса. Сейчас в auto_ptr жёстко вызывается delete, а будет возможность delete[] и других каких угодно.

Booster ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.