Eu aprendi recentemente D e estou começando a familiarizar-me com o idioma. Sei o que ele oferece, ainda não sei como usar tudo e não sei muito sobre idiomas D e assim por diante, mas estou aprendendo.
Eu gosto de D. É uma linguagem agradável, sendo, de certa forma, uma grande atualização para C, e bem feita. Nenhuma das características parece ter sido "trancada", mas na verdade muito bem pensada e bem projetada.
Você ouvirá frequentemente que D é o que C ++ deveria ter (deixo a questão de saber se isso é verdade ou não para cada um e para todos decidirem a si mesmos, a fim de evitar guerras desnecessárias). Também ouvi de vários programadores de C ++ que eles gostam de D muito mais que C ++.
Eu mesmo, enquanto conheço C, não posso dizer que conheço C ++. Eu gostaria de ouvir de alguém que conhece C ++ e D se acha que há algo que C ++ faz melhor que D como linguagem (o que significa que não é o habitual "ele tem mais bibliotecas de terceiros" ou "há mais recursos" ou " existem mais trabalhos que requerem C ++ do que D ").
O D foi projetado por alguns programadores de C ++ muito qualificados ( Walter Bright e Andrei Alexandrescu , com a ajuda da comunidade D) para corrigir muitos dos problemas do C ++, mas havia algo que realmente não melhorou afinal? Algo que ele perdeu? Algo que você acha que não era uma solução melhor?
Além disso, observe que estou falando de D 2.0 , não de D 1.0 .
fonte
Respostas:
A maioria das coisas que C ++ "faz" melhor que D são meta coisas: C ++ possui melhores compiladores, ferramentas melhores, bibliotecas mais maduras, mais ligações, mais especialistas, mais tutoriais etc. Basicamente, possui mais e melhor de todas as coisas externas que você esperaria de uma linguagem mais madura. Isso é indiscutível.
Quanto à linguagem em si, existem algumas coisas que o C ++ faz melhor que o D na minha opinião. Provavelmente há mais, mas aqui estão algumas que eu posso listar em cima da minha cabeça:
O C ++ possui um sistema de tipos melhor pensado
Há alguns problemas com o sistema de tipos em D no momento, que parecem ser omissões no design. Por exemplo, atualmente é impossível copiar uma estrutura const para uma estrutura não-const se a estrutura contiver referências ou ponteiros de objetos de classe devido à transitividade de const e à maneira como os construtores de postblit trabalham nos tipos de valor. Andrei diz que sabe como resolver isso, mas não deu detalhes. O problema é certamente corrigível (a introdução de construtores de cópia no estilo C ++ seria uma correção), mas atualmente é um grande problema na linguagem.
Outro problema que me incomodou é a falta de const lógica (ou seja, não é
mutable
como no C ++). Isso é ótimo para escrever código seguro para threads, mas torna difícil (impossível?) Realizar uma intalação lenta dentro de objetos const (pense em uma função const 'get' que constrói e armazena em cache o valor retornado na primeira chamada).Finalmente, dado estes problemas existentes, eu estou preocupado com a forma como o resto do sistema tipo (
pure
,shared
, etc.) irão interagir com tudo o resto na língua uma vez que eles são colocados em uso. Atualmente, a biblioteca padrão (Phobos) faz muito pouco uso do sistema de tipo avançado de D, então acho razoável a questão de saber se ela será mantida sob estresse. Sou cético, mas otimista.Observe que o C ++ possui alguns tipos de verrugas do sistema (por exemplo, const não transitiva, exigindo
iterator
tambémconst_iterator
) que o tornam bastante feio, mas embora o sistema de tipos do C ++ esteja um pouco errado em algumas partes, ele não impede que você faça trabalhos como os de D às vezes faz.Edit: Para esclarecer, acredito que o C ++ tenha um sistema de tipo melhor pensado - não necessariamente melhor - se isso fizer sentido. Essencialmente, em DI, há um risco envolvido no uso de todos os aspectos de seu sistema de tipos que não estão presentes no C ++.
Às vezes, D é um pouco conveniente demais.
Uma crítica que você costuma ouvir sobre o C ++ é que ele oculta alguns problemas de baixo nível, por exemplo, atribuições simples como
a = b;
fazer várias coisas como chamar operadores de conversão, chamar operadores de atribuição de sobrecarga etc. difícil de ver a partir do código. Algumas pessoas assim, outras não. De qualquer maneira, em D é pior (melhor?) Devido a coisas comoopDispatch
,@property
,opApply
,lazy
que têm o potencial de alterar o código inocente em coisas que você não espera.Eu não acho que isso seja um grande problema pessoalmente, mas alguns podem achar isso desanimador.
D requer coleta de lixo
Isso pode ser visto como controverso, porque é possível executar D sem o GC. No entanto, apenas porque é possível, não significa que seja prático. Sem um GC, você perde muitos recursos de D e o uso da biblioteca padrão seria como caminhar em um campo minado (quem sabe quais funções alocam memória?). Pessoalmente, acho totalmente impraticável usar D sem um GC, e se você não é fã de GCs (como eu sou), isso pode ser bastante desanimador.
Definições de matriz ingênua em D alocam memória
Esta é uma das minhas preocupações:
Aparentemente, para evitar a alocação em D, você deve fazer:
Essas pequenas alocações "pelas costas" são bons exemplos dos meus dois pontos anteriores.
Editar: Observe que esse é um problema conhecido que está sendo trabalhado.Edit: Agora está corrigido. Nenhuma alocação ocorre.
Conclusão
Concentrei-me nos negativos de D vs C ++ porque é isso que a pergunta fazia, mas não veja este post como uma declaração de que C ++ é melhor que D. Eu poderia facilmente fazer um post maior de lugares onde D é melhor que C ++. Cabe a você tomar a decisão de qual usar.
fonte
Quando entrei para o desenvolvimento de D, eu estava na posição peculiar de ser uma das pessoas que mais sabem sobre C ++. Agora estou na posição ainda mais peculiar de ser também uma das pessoas que mais sabem sobre D. Não estou dizendo isso aos direitos de crédito ou de se gabar tanto quanto para observar que estou curiosamente posição privilegiada para responder a esta pergunta. O mesmo se aplica a Walter.
Em geral, perguntar o que C ++ (e com isso quero dizer C ++ 2011) é melhor que D é tão autocontraditório quanto a pergunta: "Se você paga um profissional para limpar sua casa, quais são os lugares que eles deixarão mais sujo do que antes? " Qualquer que tenha sido o valor que o C ++ poderia fazer, o D não pôde, sempre foi um problema para mim e Walter, então quase por definição não há nada que o C ++ possa fazer que não esteja ao alcance de D.
Uma coisa que raramente é entendida no design da linguagem (porque poucas pessoas têm a sorte de realmente fazer alguma) é que há muito menos erros não forçados do que parece. Muitos de nós, usuários de idiomas, examinamos uma construção ou outra e dizemos: "Eca! Isso é tão errado! O que eles estavam pensando?" O fato é que a maioria das instâncias embaraçosas de uma língua é consequência de algumas decisões fundamentais que são sólidas e desejáveis, mas que competem fundamentalmente ou se contradizem (por exemplo, modularidade e eficiência, concreção e controle, etc.).
Com tudo isso em mente, vou enumerar algumas coisas em que consigo pensar e, para cada uma, explicarei como a escolha de D deriva do desejo de cumprir outra carta de nível superior.
D assume que todos os objetos são móveis por cópia bit a bit. Isso deixa uma minoria de projetos para o C ++, especificamente aqueles que usam ponteiros internos, ou seja, uma classe que contém ponteiros dentro de si. (Qualquer projeto desse tipo pode ser traduzido com custo de eficiência desprezível ou desprezível em D, mas haveria um esforço de tradução envolvido.) Tomamos essa decisão de simplificar bastante o idioma, tornar a cópia de objetos mais eficiente sem intervenção mínima ou do usuário e evitar o pântano inteiro da construção da cópia e as referências rvalue são exibidas por completo.
D proíbe tipos de gênero ambíguo (que não podem decidir se são de valor ou de referência). Tais projetos são evitados por unanimidade em C ++ e quase sempre estão errados, mas alguns deles são tecnicamente corretos. Fizemos essa escolha porque ele não permite o código incorreto e apenas uma pequena fração do código correto que pode ser redesenhado. Acreditamos que é uma boa troca.
D não permite hierarquias de várias raízes. Um pôster anterior aqui ficou muito empolgado com esse tópico em particular, mas esse é um terreno bem trilhado e não há vantagem palpável de hierarquias sem raiz sobre hierarquias que possuem uma raiz comum.
Em D você não pode jogar, por exemplo, um int. Você deve lançar um objeto que herda Throwable. Não há dúvida de que o estado das coisas é melhor em D, mas, bem, é uma coisa que o C ++ pode fazer que D não pode.
Em C ++, a unidade de encapsulamento é uma classe. Em D é um módulo (ou seja, arquivo). Walter tomou essa decisão por dois motivos: mapear naturalmente o encapsulamento para a semântica da proteção do sistema de arquivos e evitar a necessidade de "amigo". Essa opção se integra muito bem ao design de modularidade geral da D. Seria possível mudar as coisas para se parecerem com C ++, mas isso forçaria as coisas; As opções de escopo de encapsulamento do C ++ são boas apenas para o design físico do C ++.
Pode haver uma ou duas coisas menores, mas no geral deve ser isso.
fonte
Object*
tão amplamente usado como umint*
?) E D parece estar ignorando completamente a penalidade de desempenho ou alegando que não existe. Isso é obviamente falso - a falta de cache é bastante perceptível em muitos casos, portanto, o C ++ sempre terá essa vantagem de flexibilidade sobre D.Eu acho que você vai ter muita dificuldade em encontrar muito em D, que é objetivamentepior que C ++. A maioria dos problemas com D, nos quais você poderia objetivamente dizer que é pior, são problemas de qualidade de implementação (geralmente devido à rapidez com que a linguagem e a implementação são jovens e estão sendo corrigidos a uma velocidade vertiginosa ultimamente) ou são problemas com a falta de bibliotecas de terceiros (que virão com o tempo). A linguagem em si é geralmente melhor que C ++, e os casos em que C ++, como linguagem, é melhor geralmente são onde há uma troca em que C ++ foi por um lado e D foi por outro, ou onde alguém tem razões subjetivas para explicar o motivo. pense que um é melhor que outro. Mas o número de razões objetivas definitivas pelas quais o C ++, como linguagem, é melhor, provavelmente será muito pequeno.
Na verdade, tenho que arruinar meu cérebro para encontrar razões pelas quais C ++, como linguagem, é melhor que D. O que geralmente me vem à mente é uma questão de troca.
Como a const de D é transitiva e porque a linguagem é imutável , ela tem garantias muito mais fortes do que as de C ++
const
, o que significa que D não possui e não pode termutable
. Não pode ter const lógico . Então, você obtém um grande ganho com o sistema const de D, mas em algumas situações, você simplesmente não pode usarconst
como usaria em C ++.D possui apenas um operador de conversão, enquanto C ++ possui 4 (5 se você contar o operador de conversão C). Isso torna mais fácil lidar com elencos em D em geral, mas é problemático quando você realmente deseja as complicações / benefícios extras que
const_cast
seus irmãos fornecem. Mas D é realmente poderoso o suficiente para que você possa usar modelos para implementar os lançamentos de C ++; portanto, se você realmente os quiser, poderá obtê-los (e eles podem até acabar na biblioteca padrão de D em algum momento).D tem muito menos conversões implícitas que o C ++ e é muito mais provável que declare que duas funções estão em conflito entre si (forçando você a ser mais específico sobre qual das funções que você quer dizer - com conversões ou fornecendo o caminho completo do módulo ) Às vezes, isso pode ser irritante, mas evita todos os tipos de problemas de seqüestro de funções . Você sabe que está realmente chamando a função que pretende.
O sistema de módulos de D é muito mais limpo do que o # C ++ inclui (para não mencionar, muito mais rápido na compilação), mas falta qualquer tipo de espaço de nome além dos próprios módulos. Portanto, se você deseja um espaço para nome em um módulo, é necessário seguir a rota Java e usar funções estáticas em uma classe ou estrutura. Funciona, mas se você realmente deseja namespacing, obviamente não é tão limpo quanto o namespacing real. Para a maioria das situações, no entanto, o espaço para nome que os próprios módulos fornecem a você é bastante (e bastante sofisticado quando se trata de coisas como conflitos, na verdade).
Como Java e C #, D tem herança única em vez de herança múltipla, mas, diferentemente de Java e C #, oferece maneiras fantásticas de obter o mesmo efeito sem todos os problemas que a herança múltipla de C ++ possui (e a herança múltipla de C ++ pode ficar muito confusa) às vezes). D não apenas possui interfaces , mas também possui mixins de strings , mixins de modelo e alias . Portanto, o resultado final é sem dúvida mais poderoso e não possui todos os problemas que a herança múltipla de C ++.
Semelhante ao C #, D separa estruturas e classes . Classes são tipos de referência que têm herança e são derivadas
Object
, enquanto estruturas são tipos de valor sem herança. Essa separação pode ser boa e ruim. Ele se livra do problema clássico de fatiar em C ++ e ajuda a separar tipos que são realmente de valor daqueles que deveriam ser polimórficos, mas, a princípio, pelo menos, a distinção pode ser irritante para um programador de C ++. Por fim, existem vários benefícios, mas obriga a lidar com seus tipos de maneira um pouco diferente.As funções de membro das classes são polimórficas por padrão. Você não pode declara-los não virtuais . Cabe ao compilador decidir se eles podem ser (o que realmente é o caso se forem finais e não estiverem substituindo uma função de uma classe base). Portanto, isso pode ser um problema de desempenho em alguns casos. No entanto, se você realmente não precisa do polimorfismo, tudo o que você precisa fazer é usar estruturas , e isso não é um problema.
D tem um coletor de lixo embutido . Muitos do C ++ considerariam isso uma desvantagem séria e, verdade seja dita, no momento, sua implementação poderia usar algum trabalho sério. Ele está melhorando, mas definitivamente ainda não está a par do coletor de lixo do Java. No entanto, isso é atenuado por dois fatores. Primeiro, se você estiver usando principalmente estruturas e outros tipos de dados na pilha, não será um grande problema. Se o seu programa não estiver constantemente alocando e desalocando coisas no heap, tudo ficará bem. E dois, você pode pular o coletor de lixo se quiser e apenas usar C
malloc
efree
. Existem alguns recursos de idioma (como corte de matriz) com os quais você terá que evitar ou ter cuidado, e parte da biblioteca padrão não é realmente utilizável sem pelo menos algum uso do GC (particularmente o processamento de cadeias), mas você pode escrever em D sem usar o coletor de lixo se você realmente quer. A melhor coisa a fazer é provavelmente usá-lo em geral e evitá-lo onde a criação de perfil mostra que está causando problemas para o código crítico de desempenho, mas você pode evitá-lo completamente, se quiser. E a qualidade da implementação do GC melhorará com o tempo, eliminando muitas das preocupações que o uso de um GC pode causar. Portanto, em última análise, o GC não será um problema tão grande e, diferentemente do Java, você pode evitá-lo, se quiser.Provavelmente existem outros também, mas é o que eu posso pensar no momento. E se você perceber, são todas compensações. D optou por fazer algumas coisas de maneira diferente do C ++, que têm vantagens definidas sobre como o C ++ faz isso, mas também têm algumas desvantagens. O que é melhor depende do que você está fazendo e, em muitos casos, provavelmente parecerá pior no começo e, em seguida, você não terá problemas com isso quando se acostumar. De qualquer forma, os problemas em D geralmente serão novos, causados por coisas novas que outras linguagens não fizeram antes ou não da maneira que D fez. No geral, D aprendeu muito bem com os erros do C ++.
E D, como linguagem, melhora o C ++ de tantas maneiras que acho que geralmente é o caso de D ser objetivamente melhor.
D tem compilação condicional . Esse é um dos recursos que frequentemente sinto falta quando estou programando em C ++. Se o C ++ o adicionasse, o C ++ melhoraria aos trancos e barrancos quando se trata de coisas como modelos.
D tem reflexão em tempo de compilação .
As variáveis são locais de encadeamento por padrão, mas podem ser,
shared
se você desejar. Isso torna o tratamento de threads muito mais limpo do que em C ++. Você está no controle completo. Você pode usarimmutable
e passagem de mensagens para comunicação entre threads, ou você pode fazer variáveisshared
e fazê-lo o caminho C ++ com semáforos e variáveis de condição. Mesmo isso é aprimorado em C ++ com a introdução do sincronizado (semelhante ao C # e Java). Portanto, a situação de segmentação de D é muito melhor que a de C ++.Os modelos de D são muito mais poderosos que os modelos de C ++, permitindo que você faça muito mais, muito mais facilmente. E com a adição de restrições de modelo, as mensagens de erro são muito melhores do que em C ++. D torna os modelos muito poderosos e utilizáveis. Não é por acaso que o autor do Modern C ++ Design é um dos principais colaboradores de D. Acho que os modelos C ++ estão seriamente ausentes em comparação com os modelos D, e às vezes pode ser muito frustrante ao programar em C ++.
D possui programação de contrato embutida .
D tem uma estrutura de teste de unidade embutida .
D possui suporte interno para unicode com
string
(UTF-8),wstring
(UTF-16) edstring
(UTF-32). Torna mais fácil lidar com o unicode. E se você quiser apenas usarstring
e geralmente não se preocupar com o unicode, poderá - embora alguma compreensão dos conceitos básicos do unicode ajude com algumas das funções padrão da biblioteca.A sobrecarga de operador de D é muito mais agradável que a de C ++, permitindo que você use uma função para sobrecarregar vários operadores ao mesmo tempo. Um excelente exemplo disso é quando você precisa sobrecarregar os operadores aritméticos básicos e suas implementações são idênticas, exceto para o operador. Os mixins de string facilitam a tarefa, permitindo que você tenha uma definição de função simples para todos eles.
As matrizes de D são muito melhores que as matrizes de C ++. Eles não apenas são do tipo adequado com um comprimento, mas também podem ser anexados e redimensionados. Concatená-los é fácil. E o melhor de tudo, eles cortam . E isso é um grande benefício para o processamento de matriz eficiente. Strings são matrizes de caracteres em D, e não é um problema (na verdade, é ótimo!), Porque as matrizes de D são muito poderosas.
Eu poderia continuar e continuar. Muitas das melhorias que D fornece são pequenas coisas (como usar
this
para nomes de construtores ou proibir declarações ou corpos de loop em que um ponto-e-vírgula é o corpo inteiro), mas algumas são bastante grandes e, quando você adiciona tudo, contribui para uma experiência de programação muito melhor. O C ++ 0x adiciona alguns dos recursos que D possui e que faltava em C ++ (por exemplo,auto
e lambdas), mas mesmo com todas as suas melhorias, ainda não haverá muito que seja objetivamente melhor sobre C ++ como linguagem que D.Não há dúvida de que existem muitas razões subjetivas para gostar uma da outra, e a imaturidade relativa da implementação de D pode ser um problema às vezes (embora tenha melhorado muito rapidamente ultimamente - especialmente desde que os repositórios foram movidos para o github ) , e a falta de bibliotecas de terceiros pode definitivamente ser um problema (embora o fato de D poder chamar facilmente funções C - e, em menor grau, funções C ++ - atenue definitivamente o problema). Mas esses são problemas de qualidade de implementação, e não problemas com o próprio idioma. E à medida que a qualidade dos problemas de implementação for corrigida, será muito mais agradável usar o D.
Portanto, suponho que a resposta curta a essa pergunta seja "muito pequena". D, como linguagem, geralmente é superior ao C ++.
fonte
RAII e uso de memória da pilha
O D 2.0 não permite que o RAII aconteça na pilha porque removeu o valor da
scope
palavra - chave na alocação de instâncias de classe na pilha.Você não pode fazer herança de tipo de valor em D, tão efetivamente que o força a fazer uma alocação de heap para qualquer forma de RAII.
Ou seja, a menos que você use
emplace
, mas é muito doloroso de usar, pois você precisa alocar a memória manualmente. (Ainda não achei prático usá-loemplace
em D.)fonte
C ++ é muito melhor em forçar você a ser detalhado. Isso pode ser melhor ou pior aos seus olhos, dependendo se você gosta de inferência ou verbosidade.
Compare a memorização em tempo de execução no C ++ :
com a mesma coisa em D:
Observe, por exemplo, a verbosidade extra com
template <typename ReturnType, typename... Args>
versus(F)
,Args...
versusArgs
,args...
versusargs
etc.Para melhor ou pior, C ++ é mais detalhado.
Obviamente, você também pode fazer isso em D:
e pareceriam quase idênticos, mas isso exigiria a
delegate
, enquanto o original aceitava qualquer objeto que pudesse ser chamado. (A versão C ++ 0x requer umstd::function
objeto, de qualquer forma, é mais detalhado e restritivo em suas entradas ... o que pode ser bom se você gosta de verbosidade e ruim se não.)fonte
Eu não sei muito sobre D, mas muitos programadores de C ++ que eu conheço detestam bastante, e eu pessoalmente tenho que concordar - eu não gosto da aparência de D e não levarei mais perto.
Para entender por que D não está ganhando mais força, você precisa entender o que atrai as pessoas para C ++. Em uma palavra, a razão número um é o controle. Quando você programa em C ++, tem total controle sobre seu programa. Deseja substituir a biblioteca padrão? Você pode. Deseja fazer lançamentos de ponteiros inseguros? Você pode. Deseja violar a correção constante? Você pode. Deseja substituir o alocador de memória? Você pode. Deseja copiar a memória bruta sem considerar seu tipo? Se você realmente quer. Deseja herdar de várias implementações? É o seu funeral. Inferno, você pode até obter bibliotecas de coleta de lixo, como o coletor Boehm. Então você tem problemas como desempenho, que seguem de perto o controle - quanto mais controle um programador tiver, mais otimizado ele poderá criar seu programa.
Aqui estão algumas coisas que eu vi ao fazer uma pequena pesquisa e falar com algumas pessoas que tentaram:
Hierarquia de tipo unificado. Os usuários de C ++ usam herança muito raramente, a maioria dos programadores de C ++ prefere composição e os tipos só devem ser vinculados por herança se houver uma boa razão para fazê-lo. O conceito de objeto viola fortemente esse princípio, vinculando todos os tipos. Além disso, está violando um dos princípios mais básicos do C ++ - você só usa o que deseja. Não ter a opção de herdar do Object, e os custos que o acompanham, são muito fortes contra o que o C ++ representa como uma linguagem em termos de dar ao programador controle sobre seu programa.
Ouvi falar de problemas com funções e delegados. Aparentemente, D tem funções e delegados como tipos de função que podem ser chamados em tempo de execução, e eles não são os mesmos, mas são intercambiáveis ou ... alguma coisa? Meu amigo teve alguns problemas com eles. Definitivamente, esse é um downgrade do C ++, que apenas possui
std::function
e pronto.Então você tem compatibilidade. D não é particularmente compatível com C ++. Quero dizer, nenhuma linguagem é compatível com C ++, vamos ser sinceros, exceto C ++ / CLI, que é meio trapaceiro, mas como barreira à entrada, isso precisa ser mencionado.
Então, existem outras coisas. Por exemplo, basta ler a entrada da Wikipedia.
printf
é uma das funções mais inseguras já criadas, na mesma família de grandes problemas, comogets
na antiga biblioteca C Standard. Se você procurá-lo no Stack Overflow, encontrará muitas e muitas perguntas relacionadas ao uso indevido. Fundamentalmente,printf
é uma violação do DRY- você está dando o tipo na string de formato e, em seguida, novamente quando você argumenta. Uma violação do DRY onde, se você errar, coisas muito ruins acontecem - por exemplo, se você alterou um typedef de um inteiro de 16 bits para um de 32 bits. Também não é extensível - imagine o que aconteceria se todos inventassem seus próprios especificadores de formato. Os iostreams do C ++ podem ser lentos, e sua escolha de operador pode não ser a melhor, e sua interface pode funcionar, mas eles são fundamentalmente garantidos como seguros, e o DRY não é violado e pode ser facilmente estendido. Isso não é algo que se possa dizerprintf
.Nenhuma herança múltipla. Essa não é a maneira C ++. Os programadores de C ++ esperam ter controle completo sobre seus programas e a linguagem que impõe o que você não pode herdar é uma violação desse princípio. Além disso, torna a herança (ainda mais) frágil, porque se você altera um tipo de uma interface para uma classe porque deseja fornecer uma implementação padrão ou algo assim, de repente todo o código do usuário é quebrado. Isso não é uma coisa boa.
Outro exemplo é
string
ewstring
. No C ++, já é bastante doloroso ter que converter entre eles, e essa biblioteca suporta Unicode, e essa antiga biblioteca C usa apenas e precisaconst char*
escrever versões diferentes da mesma função, dependendo do tipo de argumento de string que você deseja. Notavelmente, os cabeçalhos do Windows, por exemplo, possuem algumas macros extremamente irritantes para lidar com o problema que geralmente pode interferir no seu próprio código. A adiçãodstring
à mistura só vai piorar as coisas, já que agora, em vez de dois tipos de string, você precisa gerenciar três. Ter mais de um tipo de string aumentará os problemas de manutenção e introduzirá códigos repetitivos que lidam com strings.Scott Meyers escreve:
O isolamento de encadeamento imposto pelo idioma não é um plus. Os programadores de C ++ esperam ter controle total sobre seus programas, e a linguagem que força alguma coisa definitivamente não é o que o médico ordenou.
Também vou mencionar a manipulação de strings em tempo de compilação. D tem a capacidade de interpretar o código D em tempo de compilação. Isto não é uma vantagem. Considere as enormes dores de cabeça causadas pelo pré-processador relativamente limitado de C, bem conhecido por todos os programadores veteranos de C ++, e então imagine o quanto esse recurso será mal utilizado. A capacidade de criar código D em tempo de compilação é excelente, mas deve ser semântica , não sintática.
Além disso, você pode esperar um certo reflexo. D tem coleta de lixo, que os programadores de C ++ associarão a linguagens como Java e C #, que são bastante diretamente opostas a ela nas filosofias, e as semelhanças sintáticas também as lembrarão. Isso não é necessariamente objetivamente justificável, mas é algo que certamente deve ser observado.
Fundamentalmente, ele não oferece tanto que os programadores de C ++ já não podem fazer. Talvez seja mais fácil escrever um metaprograma fatorial em D, mas já podemos escrever metaprogramas fatoriais em C ++. Talvez em D você possa escrever um traçador de raios em tempo de compilação, mas ninguém realmente quer fazer isso de qualquer maneira. Comparado às violações fundamentais da filosofia C ++, o que você pode fazer em D não é particularmente notável.
Mesmo que essas coisas sejam apenas problemas na superfície, tenho certeza de que o fato de que D na superfície não se parece com C ++ é provavelmente uma boa razão para que muitos programadores de C ++ não estejam migrando para D. Talvez D precise fazer um trabalho melhor anunciando a si mesmo.
fonte
std::function
e pronto. Por quê? Porque você também, por exemplo, possui ponteiros de função. É exatamente a mesma coisa nas "funções" de D: D são ponteiros de função, e os "delegados" de D são os mesmos que os de C ++std::function
(exceto que eles estão embutidos). Não há "downgrade" em nenhum lugar - e há uma correspondência 1: 1 entre eles, portanto não deve ser confuso se você estiver familiarizado com C ++.Uma coisa que eu aprecio em C ++ é a capacidade de documentar um argumento de função ou retornar um valor como uma referência C ++ em vez de um ponteiro, implicando, portanto, uma não-
null
valor.Versão D:
Versão C ++:
Para ser justo, você pode se aproximar muito do C ++ transformando
A
em Dstruct
e marcando ofoo()
-argumento como aref
(classes são tipos de referência e estruturas são tipos de valor em D, semelhante ao C #).Acredito que exista um plano para criar um
NonNullable
modelo para classes como uma construção de biblioteca padrão D. Mesmo assim, eu gosto da brevidade de apenas emType&
comparação comNonNullable(Type)
, e preferiria não anulável como o padrão (renderizando algo comoType
eNullable(Type)
). Mas é tarde demais para mudar isso para D e estou me afastando do assunto agora.fonte
ref
para fornecer o mesmo efeito que os C ++&
. A única grande diferença é queref
não será temporário, mesmo que sejaconst
.A coisa mais importante que o C ++ "faz melhor" do que o D é a interface com as bibliotecas herdadas . Vários mecanismos 3D, OpenCL e similares. Como D é novo, ele tem uma quantidade muito menor de bibliotecas diferentes para escolher.
Outra diferença importante entre o C ++ e o D é que o C ++ tem vários fornecedores independentes financeiramente, mas a partir de 2014 o D tinha praticamente apenas um , a equipe de dois homens que o criou. É interessante que o "princípio da segunda fonte", que diz que os projetos nunca devem depender de tecnologia, componentes, que tenham apenas um único fornecedor, pareça válido até para o software.
Para comparação, a primeira versão do intérprete Ruby foi escrita pelo inventor de Ruby, o Yukihiro Matsumoto, mas o intérprete Ruby da era principal de 2014 foi escrito praticamente do zero por outras pessoas. Portanto, Ruby pode ser visto como uma linguagem que possui mais de um fornecedor financeiramente independente. D, por outro lado, pode ser uma tecnologia incrível, mas depende dos poucos desenvolvedores que a desenvolvem.
A história do Java mostra que, mesmo que uma tecnologia, neste caso, Java, tenha um financista fino, porém único, há um grande risco de que a tecnologia seja essencialmente descartada, independentemente da enorme base de usuários corporativos. Uma citação da Apache Software Foundation , onde a CE significa "Comitê Executivo":
A Oracle forneceu ao CE uma solicitação e licença de especificação Java SE 7 que são auto-contraditórias, restringem severamente a distribuição de implementações independentes da especificação e, o mais importante, proíbem a distribuição de implementações independentes de fonte aberta da especificação.
Como uma nota histórica, pode-se dizer que os applets Java aceleraram a tela 3D anos antes do desenvolvimento do HTML5 WebGL. O problema da velocidade de inicialização dos miniaplicativos Java poderia ter sido resolvido, se o Java tivesse sido um projeto da comunidade, mas os executivos do único financiador do Java, a Sun Microsystems, não consideraram importante o suficiente para corrigir a implementação do Java. O resultado final: a tela HTML5 de vários fornecedores como uma "réplica do pobre homem" das estruturas da GUI Java (Swing, etc.). Curiosamente, no lado do servidor, a linguagem de programação Python tem as mesmas vantagens que o Java prometeu: escreva uma vez, execute em todos os servidores, independentemente do hardware, desde que o aplicativo Python não seja compilado no código da máquina. O Python é quase tão antigo / jovem quanto o Java, mas, diferentemente do Java, ele '
Resumo:
Ao avaliar a tecnologia para uso em produção, as propriedades mais importantes das tecnologias são as pessoas que a desenvolvem, o processo social, onde o desenvolvimento ocorre e o número de equipes de desenvolvimento financeiramente independentes.
Se é mais vantajoso usar a tecnologia T1 em detrimento da tecnologia T2, depende dos fornecedores das tecnologias e se a tecnologia T1 permite resolver problemas relacionados ao projeto com menor custo que o T2. Por exemplo, se o problema do fornecedor único fosse ignorado, para os sistemas de informação o Java seria uma tecnologia "melhor" que o C ++, porque os binários Java não precisam de recompilação na implantação do novo hardware e a quantidade de trabalho de desenvolvimento de software relacionado ao gerenciamento de memória é menor para o Java do que para o C ++. Projetos desenvolvidos a partir do zero, por exemplo, projetos que não dependem de outras bibliotecas, podem ser mais baratos em D do que em C ++, mas, por outro lado, o C ++ tem mais de um fornecedor e, portanto, é menos arriscado a longo prazo. . (O exemplo de Java, onde o Sun Microsystems estava quase OK,
Uma possível solução alternativa para algumas das limitações do C ++
Uma das soluções possíveis para algumas das limitações do C ++ é usar um padrão de design, em que a tarefa inicial é dividida em partes e as partes são "classificadas" (classificadas, agrupadas, divididas, outras palavras bonitas para a mesma coisa) para 2 classes: controle tarefas relacionadas à lógica , em que os padrões de acesso à memória não permitem localidade; tarefas de processamento de sinal , onde a localidade é facilmente alcançada. As tarefas "semelhantes" ao processamento de sinal podem ser implementadas como um conjunto de programas de console relativamente simplistas. As tarefas relacionadas à lógica de controle são colocadas todas em um único script que é escrito em Ruby ou Python ou qualquer outra coisa, em que o conforto no desenvolvimento de software tem prioridade mais alta que a velocidade.
Para evitar a inicialização cara do processo do sistema operacional e a cópia de dados entre os processos do sistema operacional, o conjunto de aplicativos pequenos do console C ++ pode ser implementado como um único programa C ++ que é inicializado como um "servlet" pelo Ruby / Python / etc. roteiro. O Ruby / Python / etc. O script desliga o servlet antes da saída. Comunicação entre o "servlet" e o Ruby / Python / etc. O script ocorre sobre um pipe nomeado Linux ou algum mecanismo semelhante.
Se a tarefa inicial não se dividir facilmente em partes que podem ser classificadas para as duas classes mencionadas acima, uma coisa a tentar pode ser reformular o problema para que a tarefa inicial mude.
fonte