2010-02-18 2 views
4

Почему он не может быть обычным вызовом функций? Новый, по существу:Почему у C++ есть свой отдельный синтаксис для new & delete?

malloc(sizeof(Foo)); 
Foo::Foo(); 

Хотя удаляемый

Foo:~Foo(); 
free(...); 

Так почему же новый/удалять в конечном итоге, это собственный синтаксис вместо того, чтобы обычные функции?

+1

Не можете ли вы переопределить операторы 'new' и' delete', чтобы они * не * делали это (т. Е. Для одиночных чисел)? (Я новичок на C++). – dreamlax

+2

По умолчанию 'new' заканчивается примерно следующим образом: ' Foo * pNewFoo = (static_cast (malloc (sizeof (Foo))) -> Foo(); ' Также имейте в виду, что не требуется исключений в ответ на неудачные выделения. Синтаксис 'new' выглядит намного более чистым для меня. – JonM

+1

Теперь, когда мы находимся на нем, он немного сложнее:' Foo * p = new (malloc (sizeof (Foo)) Foo (); ', где' new (ptr) Type' в выражении называется * placement-new * и на самом деле является вызовом конструктора (код пользователя не может напрямую вызвать конструктор) –

ответ

7

Вот удар у него:

Оператор new вызывает функцию operator new(). Аналогично, оператор delete вызывает функцию operator delete() (и аналогично для версий массива).

Так почему же это? Поскольку пользователю разрешено переопределять operator new(), но не Оператор new (который является ключевым словом). Вы переопределяете operator new() (и удаляете), чтобы определить свой собственный распределитель, однако вы не отвечаете (или не допускаете этого) для вызова соответствующих конструкторов и деструкторов. Эти функции автоматически вызывается компилятором, когда он видит ключевое слово new.

Без этой дихотомии, пользователь может переопределить функцию operator new(), но компилятор все равно пришлось бы рассматривать это как специальной функции и вызвать соответствующий конструктор (ы) для объекта (ов) создается.

4

Вы можете перегрузить operator new и operator delete, чтобы предоставить свою собственную семантику выделения. Это полезно, если вы хотите обойти поведение распределителя кучи по умолчанию. Например, если вы выделяете и освобождаете множество экземпляров небольшого объекта с фиксированным размером, вы можете использовать распределитель пулов для управления памятью.

Имея new и delete, так как явные операторы, такие как другие операторы, облегчают эту гибкость при использовании механизма перегрузки оператора C++.

Для объектов auto объектов в стеке вызовы вызова/вызова вызывающего устройства/деструктора вызова конструктора прозрачны по мере запроса. :)

+0

Это звучит глубоко; но я не понимаю. Можете ли вы показать код? – anon

+0

@anon my C немного ржавый, но, по сути, если вы знаете, что вам когда-нибудь понадобится 3 какого-либо объекта, а новый/delete будет вызываться часто. Тогда вы можете сделать это Foo [3] pool; char [3] доступно = {0, 1, 2}; char top = 2; Foo allocate() {return pool [доступно [top--]]; } void deallocate (Foo * foo) {доступно [++ top] = foo - pool; } Это дает распределение O (1) (если вы придерживаетесь правил) в отличие от malloc, который должен сканировать свободные списки для доступного пространства –

1

Почему у C++ есть отдельный синтаксис для большего, чем? Почему он не может быть обычным вызовом функции?

greaterThan(foo, bar); 
+0

Это * будет * быть вызовом функции, если оператор перегружен, не будет ли он ? – dreamlax

+0

Потому что это было бы ненужным и бессмысленным отклонением от C; а также отходы нажатия клавиш. – anon

3

Потому что нет никакого способа, чтобы обеспечить Скомпилируйте время типобезопасность с функцией (таНосом() возвращает пустые *, помните). Кроме того, C++ пытается исключить даже малейшую вероятность размещения выделенных, но неинициализированных объектов. И есть объекты без конструктора по умолчанию - для них, как бы вы передали аргументы конструктора функции? Функция, подобная этой, потребует слишком большой обработки особых случаев; легче продвинуть его к языковой функции. Таким образом, оператор новый.

+0

malloc сам по себе небезопасен; но New можно сделать безопасным тип, обернув его как: Foo * new (args) {Foo * ans = (Foo *) malloc (sizeof (Foo)); Foo :: init (ans, args); } – anon

2

«new/delete» - это ключевые слова на языке C++ (например, «for» и «while»), тогда как malloc/calloc - это вызовы функций в стандартной библиотеке C (например, «printf» и «sleep»). Очень разные звери, больше, чем их аналогичный синтаксис.

Основное отличие состоит в том, что «новый» и «удалить» запускают дополнительный код пользователя - в частности, конструкторы и деструкторы. Все malloc делает выделение памяти для вас.При отмене памяти для простых простых старых данных (например, float или ints), «новый» и «malloc» ведут себя очень похоже. Но когда вы запрашиваете место для класса, «новое» ключевое слово выделяет память, а затем вызывает конструктор для инициализации этого класса. Большая разница.

 Смежные вопросы

  • Нет связанных вопросов^_^