Вопрос:
В C мы можем преобразовать void* в любые другие указатели.
Но С++ запрещает это.
int *a = malloc(4);
приводит к этой ошибке:
invalid conversion from ‘void*’ to ‘int*’ [-fpermissive]
Есть ли скрытые опасности здесь, в С++?
Есть ли примеры С++?
Лучший ответ:
В С++, в отличие от C, вы должны указать результат malloc. Ваш код может быть изменен в рабочем порядке с простым приложением.
int *a = (int *)malloc(sizeof(int));
Отличную статью об этом обязательном броске и причинах этого можно найти здесь.
Дополнительную ссылку для справки можно найти здесь.
Изменить: Как указано в комментариях, использование malloc() не должно быть обычным явлением. Ближайшая альтернатива заключается в использовании new для выделения.
int *a = new int[15];
Дополнительное редактирование: Как снова предлагается в комментариях, если вам нужно использовать malloc(), по крайней мере, использовать С++-литье.
int *a = static_cast<int*>malloc(sizeof(int)); // shout out to @edheal, @mgetz Ответ №1
Вы можете выполнить преобразование в С++, но для этого требуется бросок. С++ стремится быть более безопасным для текста языком, чем C, поэтому он пытается закрыть некоторые “дыры в системе типов”, которые допускает C.
В C это будет приниматься без какой-либо диагностики:
int x; void *p = &x; double *q = p; *q = 0.0;
Безопасность типа была нарушена без каких-либо следов присутствия в исходном коде.
Это С++ FAQ, на который ответил Б. Страуструп, изобретатель С++.
С++ не запрещает преобразование; он просто хочет, чтобы он был документирован каким-то образом в исходном коде, а именно актом, который, по крайней мере, предлагает, если не доказывает, что это делается специально.
О происхождении void *, Stroustrup пишет это (смелый мой):
В конце своей истории C с классами * начал поддерживать понятие указателя на “необработанную память”, void *. Происхождение void * окутано какой-то тайной. Я смутно помню, как он изобрел его вместе с Ларри Рослер и Стив Джонсон. Тем не менее, Дэйв Проссер вспоминает сначала, предложив его на основе чего-то “где-то в Австралии”. Возможно, обе версии верны, потому что Дейв тесно сотрудничал с Ларри в то время. В любом случае void * был введен на обоих языках более или менее в то же время. Самое раннее упоминание void *, которое я могу найти, находится в памятке от 1 января 1983 года о механизмах управления памятью, предоставляемых моим компилятором С++, Cfront, поэтому происхождение void * на С++ должно вернуться к до середины 1982 года. Самая ранняя письменная запись void * в контексте ANSI C – это предложение Майка Мейснера от 12 октября 83 года, которое представило void * по существу, поскольку оно было принято в ANSI C в июне 1984 года [Prosser, 2001]
Таким образом, С++ наследует концепцию void *, как первоначально предполагал Stroustrup, в то же время люди C имели немного другую идею, которая была более свободной в безопасности типов.
В случае malloc, конечно, есть опасности; но они уже отмечены наличием известного идентификатора malloc; приведение не приводит к чему-либо еще, но не требует его специально для malloc, тогда как его требование везде будет неудобным исключением из правил.
* “C с классами” является предшественником С++