ponteiros vazios:diferença entre C e C++
-
20-09-2019 - |
Pergunta
Estou tentando entender as diferenças entre C e C++ em relação aos ponteiros vazios.as seguintes compilações em C, mas não em C++ (todas as compilações feitas com gcc/g++ -ansi -pedantic -Wall):
int* p = malloc(sizeof(int));
Porque malloc
retorna void*
, que C++ não permite atribuir a int*
enquanto C permite isso.
No entanto, aqui:
void foo(void* vptr)
{
}
int main()
{
int* p = (int*) malloc(sizeof(int));
foo(p);
return 0;
}
Tanto C++ quanto C compilam sem reclamações.Por que?
K&R2 dizem:
Qualquer ponteiro para um objeto pode ser convertido para tipo
void *
sem perda de informação.Se o resultado for convertido de volta ao tipo de ponteiro original, o ponteiro original será recuperado.
E isso resume tudo o que há sobre void*
conversões em C.O que o padrão C++ dita?
Solução
Em C, conversões de ponteiro de e para void*
estavam sempre implícitos.
Em C ++, conversões de T*
para void*
estão implícitos, mas void*
Para qualquer outra coisa, é necessário um elenco.
Outras dicas
O C ++ é mais fortemente do que C. Muitas conversões, especialmente aquelas que implicam uma interpretação diferente do valor, requerem uma conversão explícita. o novo O operador em C ++ é uma maneira segura para alocar memória na pilha, sem um elenco explícito.
É útil entender que as conversões do tipo ponteiro não requerem realmente a execução de instruções extras da CPU.Eles são analisados durante o tempo de compilação para entender as intenções do desenvolvedor. void *
é um ponteiro opaco.Tudo indica que o tipo de objeto pontiagudo é desconhecido.C é digitado fracamente.Permite a conversão direta entre (void *
) e qualquer (T*
) implicitamente.C++ é fortemente tipado.Uma conversão de (void *
) para (T*
) não seria realmente um bom argumento para uma linguagem fortemente tipada.Mas o C++ tinha que permanecer compatível com versões anteriores do C, portanto, tinha que permitir tais conversões.O princípio orientador então é:explícito é melhor que implícito.Portanto, se você deseja converter um (void*
) para algum específico (T*
), você precisa escrevê-lo explicitamente no código.Conversão de (T*
) para (void*
) não requer conversão explícita, pois não há nada que se possa fazer diretamente em um ponteiro (void*) (embora seja possível chamar free()).Por isso (T*
) para (void*
) a conversão é praticamente segura.