Каков эквивалент нового/удалять из C++ в C?
Или это - то же в C/C++?
В Си нет выражения new
/delete
.
Ближайшим эквивалентом являются функции malloc
и free
, если игнорировать конструкторы/деструкторы и безопасность типов.
#include <stdlib.h>
int* p = malloc(sizeof(*p)); // int* p = new int;
...
free(p); // delete p;
int* a = malloc(12*sizeof(*a)); // int* a = new int[12];
...
free(a); // delete[] a;
Не является точной копией, но совместимые эквиваленты являются malloc и бесплатными.
<data-type>* variable = (<data-type> *) malloc(memory-size);
free(variable);
Никаких конструкторов / деструкторов - C в любом случае их не имеет :)
Чтобы получить размер памяти, вы можете использовать оператор sizeof
.
Если вы хотите работать с многомерными массивами, вам нужно будет использовать его несколько раз (как новый):
int** ptr_to_ptr = (int **) malloc(12 * sizeof(int *)); //assuming an array with length 12.
ptr[0] = (int *) malloc(10 * sizeof(int)); //1st element is an array of 10 items
ptr[1] = (int *) malloc(5 * sizeof(int)); //2nd element an array of 5 elements etc
Обратите внимание, что в C++ конструкторы могут бросать исключения. Эквивалент player* p = new player();
в Си был бы примерно таким.
struct player *p = malloc(sizeof *p);
if (!p) handle_out_of_memory();
int err = construct_player(p);
if (err)
{
free(p);
handle_constructor_error();
}
Эквивалент delete p
проще, потому что деструкторы никогда не должны "бросать".
destruct(p);
free(p);
Использование 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, чем о языке OO)