Недавно я прочитал статью, в которой говорилось, что в C нет необходимости явно приводить типы malloc и calloc, но в C++ это обязательно. Почему это так? Кто-нибудь может объяснить?
Почему обязательно явно указывать типы malloc и calloc в C++?
Ответы (2)
Потому что в C очень часто нужно использовать void *
для разных случаев. Некоторые из них являются файлами cookie для обратного вызова — когда вы предоставляете указатель на пользовательские данные, и у вас нет способа узнать этот тип данных. Или универсальные функции, такие как qsort()
, они должны работать с различными данными, не зная заранее их тип. Однако в C++ вам не нужно использовать void *
так часто, а в хорошем безопасном коде вам вообще не нужно их использовать, потому что у вас есть шаблоны, поэтому вы пишете общий код с использованием неизвестных типов без небезопасных преобразований. Поэтому создатели C++ хотели стимулировать правильное использование типов данных и убедиться, что когда разработчик выполняет небезопасные операции, он/она/оно/они понимает, что он/она/оно/они делает.
Поскольку malloc()
и calloc()
возвращают void *
, вы должны явно преобразовать их в C++. Обратите внимание, что вы не должны использовать их в С++, а вместо этого использовать operator new
, который уже возвращает правильный тип указателя, и вам не нужно приведение. И уж тем более в современном C++ не рекомендуется даже напрямую вызывать new
.
В C ему задано T *tp; U *up; void *vp;
, можно сказать vp = tp; up = vp;
и в итоге получить U*
, который содержит адрес T
, без использования каких-либо операторов приведения. Разработчики C++, однако, хотели гарантировать, что подобное невозможно без использования хотя бы одного явного оператора приведения типов. В большинстве случаев требование использования оператора приведения между моментом представления указателя в виде void*
и временем его фактического использования менее неприятно, чем требование оператора приведения при преобразовании указателя в void*
, что и делает C++. Ни C, ни C++ не допускают каких-либо синтаксических различий между void*
, который был создан путем преобразования адреса объекта с реальным типом, и тем, который используется для хранения адреса большого двоичного объекта хранения без типа и, следовательно, не имеет способ позволить последнему неявно преобразовываться в любой тип (что было бы полезно), не делая того же с первым (чего разработчики C++ не хотели).
void *
в cpp не преобразуется неявно, тогда как в C это происходит. Так устроен язык. - person gstukelj   schedule 18.12.2019void *
. Если бы это было возможно, то вы могли бы сделать что-то простое вроде этого:void *ptr = nullptr; char* a = ptr;
, но вы получите ту же ошибку без приведения. - person PaulMcKenzie   schedule 18.12.2019