O Calcanhar de Aquiles do C++ e a Futura (R)evolução
Este artigo explora as limitações inerentes ao C++ que impedem sua evolução e discute a necessidade de uma linguagem substituta. Analisa os desafios enfrentados pelas linguagens "matadoras de C++" e propõe que uma abordagem de transpilação incremental pode ser a chave para uma adoção mais ampla.
MundiX News·13 de abril de 2026·7 min de leitura·👁 3 views
Recentemente, publiquei uma opinião sobre o modelo econômico fundamental do desenvolvimento de software, que não promove (e objetivamente não deveria promover) uma transição em massa de C/C++ para linguagens de programação "seguras".
No entanto, para ser honesto com os leitores, decidi publicar também um artigo de contra-argumento com uma descrição do outro lado da moeda, ou seja, por que o C++ ainda será substituído mais cedo ou mais tarde, e ao mesmo tempo tentar analisar qual será a nova linguagem de programação que inevitavelmente substituirá o C++.
Problemas do C++ e o beco sem saída da evolução
A impossibilidade de gerenciamento seguro de memória e o comportamento indefinido (Undefined Behavior - UB) tornaram-se parte do padrão C++. Eles estão embutidos em sua base. Macros, arquivos de cabeçalho, especialização parcial, SFINAE, regras de inicialização - qualquer tentativa de mudar o C++ muitas vezes se depara com o fato de que já existe muito código legal que depende das regras atuais. E é necessário manter o comportamento antigo, porque abandonar o UB ou mudar para um modelo de gerenciamento de memória estrito e verificável quebra imediatamente muitas suposições no código existente, ou criar um novo conceito em paralelo com o antigo, o que aumenta ainda mais a complexidade da linguagem.
Portanto, por trás do sucesso do C++ esconde-se um paradoxo: quanto mais estabelecido se torna o padrão da linguagem, mais difícil é fazer mudanças nela. Organizacionalmente, isso significa a necessidade de sincronizar um grande número de participantes no processo: desenvolvedores de compiladores, bibliotecas, representantes de empresas e especialistas independentes, cada um representando diferentes interesses. Alguém está lutando pela segurança da memória, alguém - por sobrecarga zero (zero overhead), e tudo isso acontece levando em conta as obrigações para com o empregador e as ambições pessoais.
Como resultado, o C++ se encurralou. Seus problemas são conhecidos há décadas, as propostas são discutidas há anos, e apenas adições que quase não entram em conflito com nada e, portanto, não afetam nada podem ser rapidamente aceitas no padrão :-(. E para uma linguagem que pretende ser a principal ferramenta de programação de sistemas, isso já não é uma desvantagem. Este é o calcanhar de Aquiles.
O paradoxo dos modernos "C++ killers"
Portanto, não é surpreendente que linguagens "matadoras de C++" surjam regularmente. Quase toda nova linguagem de sistema em algum momento se posicionou como candidata a substituir o C++: memória mais segura, melhor paralelismo, erros mais compreensíveis, modelo de desenvolvimento mais moderno. Muitas dessas linguagens são realmente bem-sucedidas em seus nichos e muitas vezes superam o C++ em ergonomia e segurança. Mas como um substituto para o C++, no sentido de deslocá-lo em massa das grandes bases de código existentes, elas não têm sucesso. E a razão aqui muitas vezes não é a sintaxe e nem mesmo a qualidade do compilador.
A principal barreira é a compatibilidade. C++ não é apenas uma linguagem. São bibliotecas, ABI, convenções de chamada, interfaces binárias, ferramentas de build, linkers, debuggers, profilers, sanitizers, certificações, scripts make/CMake/Bazel milenares, toneladas de cabeçalhos e macros, milhões de linhas de "cultura embutida" de codificação. Quando uma nova linguagem vem com seu próprio compilador (mesmo que use LLVM como backend), ela traz consigo um novo conjunto de limites: como misturar módulos, como linkar com bibliotecas existentes, como depurar a pilha de chamadas, como garantir a compatibilidade de exceções, RTTI, name mangling e convenções de chamada em diferentes plataformas.
Em teoria, é fácil dizer "nós temos FFI". Na prática, FFI é extern "C", o que não é suficiente para interagir com C++ com seus templates, inlines, overloads, SFINAE, ADL e a cultura de bibliotecas header-only. A maior parte do ecossistema C++ moderno não é uma API C conveniente, mas um conjunto de cabeçalhos que assumem que o consumidor também é compilado como C++ e vive pelas mesmas regras.
Por alguma razão, todas as linguagens assassinas de C++ esqueceram uma lição histórica muito útil. O compilador C++ inicial (então ainda "C com classes") - cfront - foi implementado como um transpiler que transformava um programa C++ em código-fonte C comum. Isso significava que qualquer compilador C existente instantaneamente se tornava uma forma de "compilar C++". Qualquer linker, debugger e profiler existente permaneciam no lugar. O risco de usar uma nova linguagem era reduzido muitas vezes, pois era possível começar a usar novos recursos sem requalificar os desenvolvedores e sem reconstruir todo o processo de produção.
No entanto, todos os "substitutos de C++" modernos geralmente escolhem o caminho oposto: criam seu próprio compilador e sua própria plataforma de execução (mesmo que baseada em LLVM). Tecnicamente, esta é uma escolha compreensível: é mais fácil fornecer um sistema holístico e melhor diagnóstico. Mas o preço dessa escolha é a criação de uma barreira de compatibilidade. Onde o Cfront removeu o problema da integração com o código-fonte antigo, o novo compilador o gera novamente: é necessário resolver a questão das fronteiras binárias, depuração, mistura com bibliotecas legacy, build, deploy e políticas de atualização. Como resultado, uma nova linguagem pode ser esteticamente bonita, mas torna-se uma alternativa possível apenas para novos projetos, mas não uma "substituição de C++" no sentido de migrar bases de código gigantescas.
Uma nova linguagem para substituir o C++
Portanto, o cenário mais realista para o surgimento de um verdadeiro substituto para o C++ parece diferente. Ele crescerá a partir de um transpiler que gera C ou, mais provavelmente, C++ como linguagem de destino. O transpiler oferece o principal que é necessário na escala do C++: incrementalidade. Você pode começar com um componente, um arquivo, um subsistema, sem reescrever tudo. O build permanece o mesmo, o link permanece o mesmo, o ABI permanece o mesmo, as ferramentas permanecem as mesmas.
A "nova linguagem" torna-se um frontend que gradualmente conquista território dentro do mundo existente, em vez de exigir a construção de um novo mundo ao lado. Ao mesmo tempo, é possível introduzir segurança "por padrão", deixando áreas "unsafe" explicitamente marcadas onde é necessário interagir com a realidade de baixo nível. E o mais importante: é possível ser compatível não apenas com C como o denominador mínimo, mas também com o ecossistema C++ como um todo.
Claro, transpiling não é uma panaceia e essa abordagem cria suas próprias dificuldades: qualidade do código gerado, legibilidade, correspondência de informações de depuração, precisão da exibição de abstrações de origem e a necessidade de usar compiladores C++. Mas essas dificuldades podem ser mais aceitáveis do que uma mudança em larga escala do compilador e de toda a infraestrutura. Portanto, um transpiler é uma forma de reduzir os riscos de mudar para uma nova linguagem para um valor controlável e tornar a migração para uma nova linguagem economicamente possível.
A partir disso, pode-se concluir que o mais provável é que não vença necessariamente a linguagem mais "limpa" ou "correta", mas aquela que tiver a menor barreira de uso no ecossistema já existente. O C++ já venceu assim - não pela qualidade da linguagem, mas pela facilidade de integração com as soluções já existentes. Portanto, se algum dia aparecer um substituto para o C++ que realmente se torne massivo, provavelmente começará com um transpiler: como uma extensão do C++, que é primeiramente compatível e só então mais conveniente e seguro.
[Resultados da pesquisa sobre pontos fracos e fortes do C++] (Resultados da pesquisa originais no artigo)
🛡️⚡
Pare de pesquisar. Comece a hackear.
O MundiX é seu copiloto de pentest com IA: comandos exatos, análise de outputs e próximo passo na kill chain — em segundos.
Sem cartão para começar · Planos a partir de R$49/mês
Recentemente, publiquei uma opinião sobre o modelo econômico fundamental do desenvolvimento de software, que não promove (e objetivamente não deveria promover) uma transição em massa de C/C++ para linguagens de programação "seguras".
No entanto, para ser honesto com os leitores, decidi publicar também um artigo de contra-argumento com uma descrição do outro lado da moeda, ou seja, por que o C++ ainda será substituído mais cedo ou mais tarde, e ao mesmo tempo tentar analisar qual será a nova linguagem de programação que inevitavelmente substituirá o C++.
Problemas do C++ e o beco sem saída da evolução
A impossibilidade de gerenciamento seguro de memória e o comportamento indefinido (Undefined Behavior - UB) tornaram-se parte do padrão C++. Eles estão embutidos em sua base. Macros, arquivos de cabeçalho, especialização parcial, SFINAE, regras de inicialização - qualquer tentativa de mudar o C++ muitas vezes se depara com o fato de que já existe muito código legal que depende das regras atuais. E é necessário manter o comportamento antigo, porque abandonar o UB ou mudar para um modelo de gerenciamento de memória estrito e verificável quebra imediatamente muitas suposições no código existente, ou criar um novo conceito em paralelo com o antigo, o que aumenta ainda mais a complexidade da linguagem.
Portanto, por trás do sucesso do C++ esconde-se um paradoxo: quanto mais estabelecido se torna o padrão da linguagem, mais difícil é fazer mudanças nela. Organizacionalmente, isso significa a necessidade de sincronizar um grande número de participantes no processo: desenvolvedores de compiladores, bibliotecas, representantes de empresas e especialistas independentes, cada um representando diferentes interesses. Alguém está lutando pela segurança da memória, alguém - por sobrecarga zero (zero overhead), e tudo isso acontece levando em conta as obrigações para com o empregador e as ambições pessoais.
Como resultado, o C++ se encurralou. Seus problemas são conhecidos há décadas, as propostas são discutidas há anos, e apenas adições que quase não entram em conflito com nada e, portanto, não afetam nada podem ser rapidamente aceitas no padrão :-(. E para uma linguagem que pretende ser a principal ferramenta de programação de sistemas, isso já não é uma desvantagem. Este é o calcanhar de Aquiles.
O paradoxo dos modernos "C++ killers"
Portanto, não é surpreendente que linguagens "matadoras de C++" surjam regularmente. Quase toda nova linguagem de sistema em algum momento se posicionou como candidata a substituir o C++: memória mais segura, melhor paralelismo, erros mais compreensíveis, modelo de desenvolvimento mais moderno. Muitas dessas linguagens são realmente bem-sucedidas em seus nichos e muitas vezes superam o C++ em ergonomia e segurança. Mas como um substituto para o C++, no sentido de deslocá-lo em massa das grandes bases de código existentes, elas não têm sucesso. E a razão aqui muitas vezes não é a sintaxe e nem mesmo a qualidade do compilador.
A principal barreira é a compatibilidade. C++ não é apenas uma linguagem. São bibliotecas, ABI, convenções de chamada, interfaces binárias, ferramentas de build, linkers, debuggers, profilers, sanitizers, certificações, scripts make/CMake/Bazel milenares, toneladas de cabeçalhos e macros, milhões de linhas de "cultura embutida" de codificação. Quando uma nova linguagem vem com seu próprio compilador (mesmo que use LLVM como backend), ela traz consigo um novo conjunto de limites: como misturar módulos, como linkar com bibliotecas existentes, como depurar a pilha de chamadas, como garantir a compatibilidade de exceções, RTTI, name mangling e convenções de chamada em diferentes plataformas.
Em teoria, é fácil dizer "nós temos FFI". Na prática, FFI é extern "C", o que não é suficiente para interagir com C++ com seus templates, inlines, overloads, SFINAE, ADL e a cultura de bibliotecas header-only. A maior parte do ecossistema C++ moderno não é uma API C conveniente, mas um conjunto de cabeçalhos que assumem que o consumidor também é compilado como C++ e vive pelas mesmas regras.
Por alguma razão, todas as linguagens assassinas de C++ esqueceram uma lição histórica muito útil. O compilador C++ inicial (então ainda "C com classes") - cfront - foi implementado como um transpiler que transformava um programa C++ em código-fonte C comum. Isso significava que qualquer compilador C existente instantaneamente se tornava uma forma de "compilar C++". Qualquer linker, debugger e profiler existente permaneciam no lugar. O risco de usar uma nova linguagem era reduzido muitas vezes, pois era possível começar a usar novos recursos sem requalificar os desenvolvedores e sem reconstruir todo o processo de produção.
No entanto, todos os "substitutos de C++" modernos geralmente escolhem o caminho oposto: criam seu próprio compilador e sua própria plataforma de execução (mesmo que baseada em LLVM). Tecnicamente, esta é uma escolha compreensível: é mais fácil fornecer um sistema holístico e melhor diagnóstico. Mas o preço dessa escolha é a criação de uma barreira de compatibilidade. Onde o Cfront removeu o problema da integração com o código-fonte antigo, o novo compilador o gera novamente: é necessário resolver a questão das fronteiras binárias, depuração, mistura com bibliotecas legacy, build, deploy e políticas de atualização. Como resultado, uma nova linguagem pode ser esteticamente bonita, mas torna-se uma alternativa possível apenas para novos projetos, mas não uma "substituição de C++" no sentido de migrar bases de código gigantescas.
Uma nova linguagem para substituir o C++
Portanto, o cenário mais realista para o surgimento de um verdadeiro substituto para o C++ parece diferente. Ele crescerá a partir de um transpiler que gera C ou, mais provavelmente, C++ como linguagem de destino. O transpiler oferece o principal que é necessário na escala do C++: incrementalidade. Você pode começar com um componente, um arquivo, um subsistema, sem reescrever tudo. O build permanece o mesmo, o link permanece o mesmo, o ABI permanece o mesmo, as ferramentas permanecem as mesmas.
A "nova linguagem" torna-se um frontend que gradualmente conquista território dentro do mundo existente, em vez de exigir a construção de um novo mundo ao lado. Ao mesmo tempo, é possível introduzir segurança "por padrão", deixando áreas "unsafe" explicitamente marcadas onde é necessário interagir com a realidade de baixo nível. E o mais importante: é possível ser compatível não apenas com C como o denominador mínimo, mas também com o ecossistema C++ como um todo.
Claro, transpiling não é uma panaceia e essa abordagem cria suas próprias dificuldades: qualidade do código gerado, legibilidade, correspondência de informações de depuração, precisão da exibição de abstrações de origem e a necessidade de usar compiladores C++. Mas essas dificuldades podem ser mais aceitáveis do que uma mudança em larga escala do compilador e de toda a infraestrutura. Portanto, um transpiler é uma forma de reduzir os riscos de mudar para uma nova linguagem para um valor controlável e tornar a migração para uma nova linguagem economicamente possível.
A partir disso, pode-se concluir que o mais provável é que não vença necessariamente a linguagem mais "limpa" ou "correta", mas aquela que tiver a menor barreira de uso no ecossistema já existente. O C++ já venceu assim - não pela qualidade da linguagem, mas pela facilidade de integração com as soluções já existentes. Portanto, se algum dia aparecer um substituto para o C++ que realmente se torne massivo, provavelmente começará com um transpiler: como uma extensão do C++, que é primeiramente compatível e só então mais conveniente e seguro.
[Resultados da pesquisa sobre pontos fracos e fortes do C++] (Resultados da pesquisa originais no artigo)
📤 Compartilhar & Baixar
🧰 Ferramentas recomendadas
Divulgação: alguns links são patrocinados. Podemos receber comissão se você comprar — sem custo extra para você. Só indicamos o que faz sentido para a comunidade.