Использование new
и delete
в C ++ сочетает в себе две обязанности - выделение / освобождение динамической памяти и инициализация / освобождение объекта.
Как и во всех других ответах, наиболее распространенный способ выделения и освобождения динамической памяти - это вызовы malloc
и free
. Вы также можете использовать специфичные для ОС функции, чтобы получить большой кусок памяти и распределить ваши объекты в этом, но это реже - только если у вас есть довольно специфические требования, которые malloc не удовлетворяет.
В C большинство API предоставляют пару функций, которые выполняют другие роли new
и delete
.
Например, файл API использует пару функций открытия и закрытия:
// C++
fstream* fp = new fstream("c:\\test.txt", "r");
delete fp;
// C
FILE *fp=fopen("c:\\test.txt", "r");
fclose(fp);
Возможно, fopen
использует malloc
для выделения хранилища для структуры FILE
, или он может статически выделить таблицу для максимального количества файловых указателей при запуске процесса. Дело в том, что API не требует от клиента использования malloc
и free
.
Другие API предоставляют функции, которые просто выполняют инициализацию и освобождение части контракта - эквивалентно конструктору и деструктору, что позволяет клиентскому коду использовать либо автоматическое, статическое или динамическое хранение. Одним из примеров является API pthreads:
pthread_t thread;
pthread_create( &thread, NULL, thread_function, (void*) param);
Это дает клиенту большую гибкость, но увеличивает связь между библиотекой и клиентом - клиент должен знать размер типа pthread_t
, тогда как если библиотека обрабатывает как распределение, так и инициализацию, клиенту не нужно знать размер типа, поэтому реализация может меняться без изменения клиента вообще. Ни один из них не обеспечивает такой же связи между клиентом и реализацией, как C ++. (Часто лучше думать о C ++ как о языке метапрограммирования шаблонов с vtables, чем оо-языке)