В C у вас нет выбора, кроме как ввести актерский состав где-то здесь. Я хотел бы использовать макрос, чтобы убедиться, что все сделано правильно на сайте вызова:
void
myfree_(void **ptr)
{
if (!ptr || !*ptr) return;
free(*ptr);
*ptr = 0;
}
#define myfree(ptr) myfree_((void **)&(ptr))
[Вы можете фактически назвать и функцию, и макрос "myfree", благодаря правилам C-бесконечной макро-рекурсии! Но это будет сбивать людей с толку. В ответе на долгое обсуждение ниже caf я также оговорю, что выражение *ptr = 0
здесь изменяет объект неизвестного типа с помощью псевдонима void**
, который является поведением, не определяемым во время выполнения - однако, мое информированное мнение таково, что оно не будет вызывают проблемы на практике, и это наименее плохой вариант, доступный в простом C; Мне кажется, что макрос caf, который оценивает свой аргумент дважды, гораздо реже (на мой взгляд) вызывает реальные проблемы.]
В C ++ вы можете использовать шаблонную функцию, которая лучше по трем причинам: она избавляет от необходимости брать адрес чего-либо на сайте вызовов, не нарушает корректность типа и вы получите ошибку во время компиляции вместо сбоя во время выполнения, если вы случайно передали не указатель на myfree
.
template <typename T>
void
myfree(T*& ptr)
{
free((void *)ptr);
ptr = 0;
}
Но, конечно, в C ++ у вас есть еще лучшие варианты, такие как интеллектуальные указатели и классы контейнеров.
Наконец, следует упомянуть, что опытные программисты на C отказываются от этого типа оболочки, потому что это не поможет вам, когда есть еще одна копия указателя на память, которую вы только что освободили, где-то торчать - и это именно то, когда вам нужно помощь.