Em C, não há necessidade de converter a void *
em qualquer outro tipo de ponteiro, pois ele é sempre promovido com segurança. No entanto, em C ++, este não é o caso. Por exemplo,
int *a = malloc(sizeof(int));
funciona em C, mas não em C ++. (Observação: eu sei que você não deve usar malloc
em C ++ ou, nesse caso new
, e preferir ponteiros inteligentes e / ou o STL; isso é solicitado apenas por curiosidade) Por que o padrão C ++ não permite essa conversão implícita, enquanto o padrão C faz?
c++
language-features
wolfPack88
fonte
fonte
long *a = malloc(sizeof(int));
Ops, alguém esqueceu de alterar apenas um tipo!sizeof(*a)
.malloc
não é possível retornar um ponteiro para o tipo alocado.new
é C ++ retorna um ponteiro para o tipo alocado, portanto, o código C ++ escrito corretamente nunca terá nenhumvoid *
s para transmitir.void
, C fez não . Quando essa palavra-chave / ideia foi adicionada a C, ela foi alterada para se adequar às necessidades de C. Isso foi logo após tipos de ponteiro começou a ser verificado em tudo . Veja se você pode encontrar on-line o panfleto de descrição da K&R C ou uma cópia vintage de um texto de programação em C, como o C Primer do Waite Group . O ANSI C estava cheio, com recursos suportados ou inspirados em C ++, e o K&R C era muito mais simples. Portanto, é mais correto que o C ++ estendeu o C como existia na época e o C que você conhece foi retirado do C ++.Respostas:
Como as conversões implícitas de tipo geralmente não são seguras, e o C ++ adota uma postura mais segura quanto à digitação do que C.
C geralmente permitirá conversões implícitas, mesmo que a maioria das chances seja de que a conversão seja um erro. Isso ocorre porque C assume que o programador sabe exatamente o que está fazendo e, se não, é problema do programador, não do compilador.
O C ++ geralmente não permite coisas que possam ser erros e exige que você declare explicitamente sua intenção com uma conversão de tipo. Isso ocorre porque o C ++ está tentando ser amigável ao programador.
Você pode perguntar como é amigável quando na verdade exige que você digite mais.
Bem, veja bem, qualquer linha de código, em qualquer programa, em qualquer linguagem de programação, geralmente será lida muito mais vezes do que será escrita (*). Portanto, a facilidade de leitura é muito mais importante do que a facilidade de escrever. E, ao ler, destacar conversões potencialmente inseguras por meio de projeções explícitas de tipos ajuda a entender o que está acontecendo e a ter um certo nível de certeza de que o que está acontecendo é, de fato, o que deveria acontecer.
Além disso, o inconveniente de digitar a conversão explícita é trivial em comparação com o inconveniente de horas e horas de solução de problemas para encontrar um bug causado por uma atribuição incorreta da qual você poderia ter sido avisado, mas nunca foi.
(*) Idealmente, ele será escrito apenas uma vez, mas será lido sempre que alguém precisar revisá-lo para determinar sua adequação à reutilização, e sempre que houver solução de problemas em andamento e sempre que alguém precisar adicionar código próximo a ele, e sempre que houver solução de problemas de código próximo e assim por diante. Isso é verdade em todos os casos, exceto nos scripts "escreva uma vez, execute e jogue fora" e, portanto, não é de admirar que a maioria das linguagens de script possua uma sintaxe que facilite a facilidade de escrever com total desconsideração da facilidade de leitura. Já pensou que perl é completamente incompreensível? Você não está sozinho. Pense em idiomas como "somente gravação".
fonte
void*
são mais inseguras em C ++, porque com a maneira como certos recursos de OOP são implementados em C ++, o ponteiro para o mesmo objeto pode ter um valor diferente, dependendo do tipo de ponteiro.Aqui está o que Stroustrup diz :
Ele então continua mostrando um exemplo de como o vácuo * pode ser perigoso e diz:
Por fim, ele observa:
Ele explica muito mais detalhes sobre isso em The Design and Evolution of C ++ .
Portanto, a resposta se resume a: O criador do idioma acredita que é um padrão inseguro, tornando-o ilegal e fornecendo maneiras alternativas de realizar para que o padrão normalmente era usado.
fonte
malloc
exemplo, vale a pena notar quemalloc
(obviamente) não chamará um construtor; portanto, se for um tipo de classe para o qual você está alocando memória, ser capaz de converter implicitamente no tipo de classe seria enganoso.É sempre promovido, sim, mas dificilmente seguro .
C ++ desabilita esse comportamento precisamente porque tenta ter um sistema de tipo mais seguro que C, e esse comportamento não é seguro.
Considere, em geral, estas três abordagens para a conversão de tipos:
Bem, eu sou feio e um obstáculo prático para fazer qualquer coisa, mas pode realmente ser usado onde é necessário muito cuidado. C aproximadamente optou por 2, que é mais fácil de implementar, e C ++ por 3, que é mais difícil de implementar, mas mais seguro.
fonte
Por definição, um ponteiro nulo pode apontar para qualquer coisa. Qualquer ponteiro pode ser convertido em um ponteiro nulo e, portanto, você poderá converter novamente chegando exatamente ao mesmo valor. No entanto, ponteiros para outros tipos podem ter restrições, como restrições de alinhamento. Por exemplo, imagine uma arquitetura em que os caracteres possam ocupar qualquer endereço de memória, mas os números inteiros devem começar em limites de endereço pares. Em certas arquiteturas, ponteiros inteiros podem até contar 16, 32 ou 64 bits por vez, para que um caractere * possa realmente ter um múltiplo do valor numérico de int * enquanto aponta para o mesmo local na memória. Nesse caso, a conversão de um vazio * na verdade arredondaria os bits que não podem ser recuperados e, portanto, não são reversíveis.
Simplificando, o ponteiro nulo pode apontar para qualquer coisa, incluindo coisas que outros ponteiros podem não ser capazes de apontar. Assim, a conversão para o ponteiro nulo é segura, mas não o contrário.
fonte