Filosofia de Engenharia: Bjarne Stroustrup, abstração sem sobrecarga

Principais conclusões
- Abstração sem sobrecarga. Stroustrup criou C++ para acabar com a falsa escolha entre código claro e velocidade direta no metal – a versão expressiva e a versão ajustada à mão devem compilar para o mesmo código de máquina.
- O princípio de sobrecarga zero. “Aquilo que você não usa, você não paga; aquilo que você usa, você não conseguiria escrever melhor à mão” é a regra pela qual todo recurso de C++ precisa passar.
- RAII torna isso concreto. Atrelar o tempo de vida de um recurso a um objeto na pilha dá uma limpeza determinística e segura contra exceções, sem coletor de lixo – um padrão que Rust depois adotou quase por inteiro.
- Não deixe espaço por baixo. C++ precisa continuar sendo a linguagem de mais alto nível com nada entre ela e o silício além do assembler, ou uma linguagem de nível mais baixo tomaria o seu lugar.
O princípio
“Aquilo que você não usa, você não paga. E mais: aquilo que você usa, você não conseguiria escrever melhor à mão.” – Bjarne Stroustrup, o princípio de sobrecarga zero1
Essa frase é a mais importante da programação de sistemas, e carrega duas promessas. A primeira metade diz que uma abstração precisa ser gratuita no ponto de não uso: encoste num recurso e ele lhe custa algo, ignore-o e ele não lhe custa nada – nem um byte de memória, nem um ciclo em tempo de execução. A segunda metade é a promessa mais difícil: quando você de fato usa a abstração, o compilador precisa produzir código de máquina pelo menos tão bom quanto aquilo que um programador competente teria escrito à mão para exatamente aquela tarefa. Um vector que não verifica limite algum em modo release. Um ponteiro inteligente que compila para um ponteiro cru. Um iterador que desaparece dentro de um laço bruto. A clareza sai de graça.
A maioria das linguagens força um trade-off. Você fica com a versão de alto nível, expressiva e lenta, ou desce para a versão de baixo nível, rápida e ilegível – e todo o ofício vira escolher qual dor aceitar em qual dia. A carreira inteira de Stroustrup é uma recusa desse trade-off. Ele havia sentido isso na pele: como doutorando, amava as abstrações de Simula, mas as achava lentas demais para o trabalho real, e amava a velocidade de BCPL, mas a achava baixa demais para construir qualquer coisa grande.2 C++ existe porque ele decidiu que você não deveria ter de escolher. Eficiência e abstração não eram mostradores opostos a equilibrar; deviam chegar juntas, na mesma linha de código.
Essa convicção é a mesma que sustenta o argumento de que desempenho não é um recurso que você adiciona, mas uma propriedade que você deixa de perder. Uma abstração de sobrecarga zero não é uma coisa rápida construída sobre uma linguagem lenta. É uma coisa clara que o compilador mói de volta até exatamente o que você teria escrito à mão, de modo que você nunca paga pela clareza. “Gosto que meu código seja elegante e eficiente”, ele já disse – e a palavra que importa é o e. Ele detesta ter de escolher entre as duas coisas.3
Contexto
Bjarne Stroustrup nasceu em 30 de dezembro de 1950, em Aarhus, na Dinamarca.4 Estudou matemática e ciência da computação na Universidade de Aarhus e depois foi para a Inglaterra fazer um doutorado no Computing Laboratory da Universidade de Cambridge, que concluiu em 1979. Sua tese – “Communication and control in distributed computer systems” – tratava de como distribuir o trabalho de um sistema operacional por uma rede de computadores.4
Para estudar esse problema, ele precisava construir um simulador, e escreveu a primeira versão em Simula, a linguagem norueguesa (projetada por Ole-Johan Dahl e Kristen Nygaard) que apresentou ao mundo as classes e os objetos. Stroustrup adorou. As abstrações de classe de Simula lhe permitiam organizar um programa grande e intrincado do jeito que o problema estava organizado, e não do jeito que a máquina estava – e o programa era um prazer de escrever e de modificar. Então ele tentou rodá-lo em escala, e as abstrações ruíram sob o próprio custo. A implementação era lenta demais para ser prática. Ele reescreveu o simulador em BCPL, uma linguagem de sistemas enxuta, e recuperou a velocidade – mas BCPL era tão baixo nível que construir qualquer coisa grande nela era um suplício.2 O tranco foi a ferida formativa. Ele havia usado a linguagem expressiva e pagado por isso em desempenho, depois usado a linguagem rápida e pagado por isso em todo o resto. Nenhuma das duas era aceitável. As duas metades deveriam ter sido possíveis ao mesmo tempo.
Ele levou essa queixa para os Bell Labs, em Nova Jersey, em 1979, onde de novo enfrentou um problema de sistemas distribuídos: analisar o tráfego do kernel do UNIX por uma rede. Lembrando-se de Cambridge, propôs-se a acrescentar o poder de organização de Simula ao C – uma linguagem já rápida e próxima do hardware, a linguagem de sistemas do UNIX – sem abrir mão de um grama da velocidade do C.45 Ele chamou o resultado de “C with Classes”. Em 1983, seu colega Rick Mascitti sugeriu o nome C++, o operador de incremento aplicado ao próprio C: o próximo C, um a mais, com a mesma máquina por baixo.5

O trabalho
De C with Classes a C++: um C melhor que não custa nada
O movimento original (1979–1983) foi deliberadamente modesto e exatamente certo. Pegue C – já rápido, já mapeando diretamente para o hardware, já a linguagem de sistemas em que as pessoas confiavam – e acrescente as coisas que Simula o havia ensinado a querer: classes, melhor verificação de tipos, abstração de dados.5 O ponto crucial é que ele as acrescentou como uma camada que os programadores de C não eram obrigados a pagar. Um programa em C continuava sendo um programa em C++ válido. Uma struct que não usava nenhum dos novos recursos compilava para os mesmos bytes de sempre. O novo poder era opcional, e usá-lo custava apenas aquilo que o C equivalente escrito à mão teria custado. Esse é o princípio de sobrecarga zero em embrião, presente antes mesmo de ele ter um nome para a ideia: não tribute quem não usa o recurso, e não deixe o recurso gerar código pior do que as próprias pessoas teriam escrito.
Ele documentou e estabilizou a linguagem em The C++ Programming Language (1985), o livro que a tornou amplamente disponível, e então passou décadas defendendo seu núcleo por meio do projeto de cada recurso posterior.4
O princípio de sobrecarga zero
O princípio de sobrecarga zero é a ideia que sustenta tudo, a regra contra a qual todo recurso de C++ é medido. Stroustrup o enuncia em duas partes: “Aquilo que você não usa, você não paga (em tempo ou espaço) e, mais: aquilo que você usa, você não conseguiria escrever melhor à mão.”1 A primeira cláusula é uma política tributária – nenhum recurso pode impor custo a código que não o utiliza. A segunda é um padrão de qualidade – um recurso que você de fato usa precisa compilar para código não pior do que um programador cuidadoso teria produzido à mão para aquela tarefa específica. Templates, constexpr, semântica de movimento e os contêineres e algoritmos da biblioteca padrão são todos projetados para honrá-lo; as duas exceções famosas, a informação de tipo em tempo de execução e as exceções, são exatamente os dois recursos para os quais os compiladores oferecem chaves para desligar, justamente porque contornam a regra.6
A recompensa é aquilo que soa impossível até você ver o assembly: o jeito expressivo e o jeito ajustado à mão produzem o mesmo código de máquina.

Essa identidade – o expressivo e o ajustado à mão colapsando numa única saída – é o motivo pelo qual o princípio é tanto moral quanto técnico. Ele remove a desculpa padrão do engenheiro. Se a clareza fosse genuinamente cara, você poderia justificar escrever a versão feia e rápida “porque tem de ser rápida”. A aposta de Stroustrup é que a desculpa em geral é mentira – que uma abstração bem projetada permite que você tenha a versão legível e a rápida, porque elas são a mesma versão. O custo foi pago uma vez, pelo projetista da linguagem, para que nunca mais fosse pago pelo programador.
RAII e recursos determinísticos
O princípio precisava de um mecanismo para a parte mais bagunçada da programação de sistemas: recursos que precisam ser adquiridos e depois liberados de forma confiável – memória, arquivos, locks, sockets. A coleta de lixo responde a isso abrindo mão do determinismo: a limpeza acontece em algum momento, no cronograma do coletor, o que é intolerável para um lock ou um descritor de arquivo. A resposta de Stroustrup, que ele batizou de RAII – Resource Acquisition Is Initialization (aquisição de recurso é inicialização) – atrela o tempo de vida de um recurso ao tempo de vida de um objeto na pilha.7 Você adquire o recurso num construtor; você o libera no destrutor; e, como C++ garante que o destrutor de um objeto na pilha roda no instante em que ele sai do escopo – normalmente ou via uma exceção, na ordem inversa da construção –, o recurso é liberado exatamente quando deveria, de forma determinística, sem coletor e sem nenhum free manual para esquecer.7
RAII é a sobrecarga zero tornada concreta. A chamada do destrutor é código que você teria de escrever à mão de qualquer jeito; a linguagem apenas garante que você não pode esquecer. Você ganha uma limpeza automática, segura contra exceções e determinística, e não paga nada que não pagaria escrevendo a limpeza você mesmo à mão. É o padrão de C++ que linguagens posteriores, Rust com mais destaque, adotariam quase por inteiro.
Padronização e “não deixe espaço para uma linguagem de nível mais baixo”
Stroustrup não manteve C++ como um projeto pessoal. Ele o levou ao comitê de padronização – ANSI a partir de 1989, ISO a partir de 1991 – e serviu nele por décadas, presidindo o Evolution Working Group, para que C++ fosse um padrão estável e neutro em relação a fornecedores, em vez do dialeto de uma única empresa.4 E deu ao comitê uma regra constitucional, extraída de seus princípios de projeto em The Design and Evolution of C++: “Não deixe espaço para uma linguagem de nível mais baixo abaixo de C++ (exceto o assembler).”8 O raciocínio é exato – se você pudesse escrever código mais eficiente em alguma linguagem entre C++ e o metal nu, então essa linguagem se tornaria a linguagem de sistemas preferida e C++ perderia sua razão de existir.8 Para se manter viável, C++ precisa preservar o acesso direto ao hardware do C, seu controle sobre o layout de dados e seus tipos primitivos que mapeiam um a um para a máquina.8 Nada deve ficar entre a abstração e o silício além do assembler. O princípio de sobrecarga zero, enunciado como uma fronteira competitiva: seja a linguagem de mais alto nível que ainda assim não deixa nada sobre a mesa.
O método
O método é uma única aposta – clareza e velocidade são a mesma coisa se você projetar a abstração corretamente – imposta como um conjunto de regras duras.
Meça cada recurso contra a sobrecarga zero. Nenhum recurso pode tributar código que não o utiliza, e nenhum recurso pode gerar código pior do que o equivalente escrito à mão. Esta é a barreira pela qual toda adição a C++ teve de passar por quarenta anos.16
Confie no programador e mantenha-se multiparadigma. C++ dá suporte aos estilos procedural, orientado a objetos, genérico e funcional porque Stroustrup recusou-se a decidir por você como organizar seu problema. A linguagem lhe dá as ferramentas e presume que você conhece seu domínio melhor do que o projetista da linguagem conhece.6
Mapeie diretamente para o hardware. Preserve a correspondência um a um do C entre tipos primitivos, layout de dados e a máquina. A abstração fica sobre o metal, não sobre um ambiente de execução que o esconde.8
Torne a limpeza determinística, não eventual. RAII vincula o tempo de vida do recurso ao tempo de vida do objeto, de modo que a liberação acontece num instante conhecido, segura contra exceções, sem coletor de lixo e sem nada de que precise lembrar de liberar.7
Estabilize-a em aberto. Entregue a linguagem a um comitê internacional de padronização em vez de detê-la, para que C++ seja um padrão público duradouro e nenhum fornecedor isolado possa fazer um fork dela.4
Cadeia de influência
Quem o moldou
Ole-Johan Dahl e Kristen Nygaard, via Simula. Simula ensinou a Stroustrup para que serve a abstração – deixar que um programa seja estruturado do jeito que o problema é estruturado – e sua lentidão lhe ensinou a outra metade da lição: que a abstração não vale nada se você não pode se dar ao luxo de usá-la. C++ é a tentativa de preservar a dádiva de Simula sem pagar nada de seu custo. (Influência direta, formativa)
BCPL e a cultura de programação de sistemas em torno de C e UNIX. BCPL lhe deu a dor contrastante – velocidade crua sem nenhum jeito de organizar qualquer coisa grande – e C, a linguagem do UNIX nos Bell Labs, lhe deu a base rápida e mapeada ao hardware sobre a qual construir C++ em cima, em vez de construir no lugar dela.25 (Influência direta)
Bell Labs. A mesma instituição que produziu C e UNIX deu a Stroustrup o problema de sistemas distribuídos que iniciou o “C with Classes” e a cultura de pesquisa que lhe permitiu passar anos acertando a linguagem. (Influência formativa)
Quem ele moldou
A infraestrutura do mundo roda na linguagem dele. Sistemas operacionais, navegadores, bancos de dados, engines de jogos, compiladores, sistemas de negociação de alta frequência, o software de voo dos rovers de Marte – o núcleo crítico em desempenho da computação moderna é desproporcionalmente C++. O trabalho de poucos engenheiros sustenta tanto peso.
O movimento das abstrações de custo zero. O princípio de Stroustrup, rebatizado de “zero-cost abstractions”, tornou-se um objetivo fundador explícito de Rust, que adotou RAII (como ownership e Drop), destruição determinística e a regra de que construções de alto nível precisam compilar para código de máquina ótimo. Linguagens como D e Carbon descendem da mesma linhagem. A ideia de que você não deveria pagar pela clareza hoje é mainstream, e ela é dele.6
O fio condutor
John Carmack quer que o laço interno faça o mínimo de trabalho que a física permite – “a velocidade da luz é uma droga”, a máquina governada por limites rígidos, cada ciclo desperdiçado uma escolha. Stroustrup entrega a Carmack as ferramentas para escrever esse laço de forma legível: uma abstração de sobrecarga zero é a promessa de que a versão clara e a versão mais próxima do metal são o mesmo código de máquina, de modo que você nunca precisa escolher. Onde Barbara Liskov deu à abstração sua teoria – a abstração de dados, o contrato que um tipo deve a seus usuários, a linhagem de Simula a CLU do “você deve programar contra aquilo que uma coisa faz, não contra como ela funciona” –, Stroustrup deu a essa teoria um corpo que não custa nada para executar. E onde Alan Kay imaginou objetos como pequenos computadores trocando mensagens, uma conversa de vinculação tardia em tempo de execução, Stroustrup tomou o caminho oposto para chegar à mesma palavra: seus objetos são resolvidos em tempo de compilação e se dissolvem em código de máquina cru, OOP como uma ferramenta de organização de sobrecarga zero, e não como um barramento vivo de mensagens. Mesmo vocabulário, duas filosofias – uma otimizando para a flexibilidade, a outra para a conta em tempo de execução. (Ponte da série)
O que eu levo disso
A lição que guardo é que “expressivo ou rápido” é quase sempre uma falsa escolha que um projeto ruim impõe a você. Quando me pego escrevendo a versão feia “porque tem de ser rápida”, o princípio de Stroustrup é a acusação: isso não é uma lei da computação, é uma falha em encontrar a abstração que compila, por conta própria, para a coisa rápida. O trabalho é projetar a versão clara tão bem que a máquina produza a partir dela o código ótimo – pagar o custo uma vez, no projeto, para que nunca mais seja pago em cada linha que a utiliza. É o mesmo padrão de qualidade ser a única variável: a pergunta nunca é “posso me dar ao luxo de tornar isto claro?”, mas “por que minha abstração vaza tanto a ponto de a clareza custar qualquer coisa?”.
No mundo em que construo agora – agentes, laços de ferramentas, sistemas de IA –, a tentação é o oposto da sobrecarga zero: empilhar um wrapper sobre outro wrapper, gastar uma chamada de modelo para encobrir um caminho lento, deixar cada abstração conveniente acrescentar silenciosamente uma latência que ninguém mede. O movimento de Stroustrup é exigir que a interface conveniente compile para a eficiente – que a API limpa e o caminho rápido sejam o mesmo caminho, com o custo pago no projeto da estrutura local em vez de cobrado de cada chamada que passa por ela. Essa convicção – a de que bom gosto é um sistema técnico contra o qual você pode opor uma regra dura, e não uma vibração que você afirma – é o fio condutor que vai de um simulador de 1979 que rodava lento demais a uma estrutura de agente de 2026 que não deveria.
FAQ
Qual é a filosofia de engenharia de Bjarne Stroustrup?
A convicção de Stroustrup é que você nunca deveria ter de escolher entre código expressivo, de alto nível, e desempenho direto no metal. Ele construiu C++ sobre o princípio de sobrecarga zero: um recurso da linguagem precisa não custar nada quando você não o usa, e, quando você o usa, precisa compilar para código não pior do que o que você teria escrito à mão para aquela tarefa.1 Ele combinou isso com confiar no programador (C++ é deliberadamente multiparadigma), mapear diretamente para o hardware, gerenciamento determinístico de recursos por meio de RAII e estabilizar a linguagem como um padrão ISO aberto, em vez de detê-la.467
O que é o princípio de sobrecarga zero?
É a regra que Stroustrup enuncia em duas partes: “Aquilo que você não usa, você não paga (em tempo ou espaço) e, mais: aquilo que você usa, você não conseguiria escrever melhor à mão.”1 A primeira metade significa que um recurso não usado não impõe custo de tempo de execução nem de memória; a segunda significa que um recurso que você de fato usa gera código pelo menos tão bom quanto o que um programador competente escreveria à mão. É a barreira pela qual todo recurso de C++ precisa passar. Os dois recursos que a contornam – a informação de tipo em tempo de execução e as exceções – são exatamente os dois que a maioria dos compiladores deixa você desligar.6 O princípio é o motivo pelo qual uma abstração de C++ como um ponteiro inteligente ou um iterador pode compilar para o mesmo código de máquina que a versão crua, ajustada à mão.
O que é RAII, e por que Stroustrup o inventou?
RAII – Resource Acquisition Is Initialization (aquisição de recurso é inicialização) – é o padrão de C++, batizado por Stroustrup, que atrela o tempo de vida de um recurso ao tempo de vida de um objeto na pilha: você adquire o recurso no construtor do objeto e o libera no destrutor.7 Como C++ garante que o destrutor de um objeto na pilha roda no momento em que ele sai do escopo – quer a função retorne normalmente, quer uma exceção desempilhe a pilha –, recursos como memória, arquivos, locks e sockets são liberados de forma determinística, num instante conhecido, sem coletor de lixo e sem nada para liberar manualmente. Ele lhe dá uma limpeza automática e segura contra exceções com sobrecarga zero, e Rust depois o adotou quase por inteiro como ownership e Drop.7
Por que Stroustrup criou C++, e de onde ele veio?
Enquanto escrevia seu doutorado em Cambridge sobre sistemas distribuídos (concluído em 1979), Stroustrup construiu um simulador em Simula e amou suas abstrações de classe, mas as achou lentas demais em escala; ele o reescreveu em BCPL, que era rápido, mas baixo demais para construir qualquer coisa grande.2 Nenhum dos trade-offs era aceitável, então, nos Bell Labs – diante de um problema de análise do kernel do UNIX por uma rede –, ele propôs-se a acrescentar o poder de organização de Simula ao C sem perder a velocidade do C. Ele chamou isso de “C with Classes” (1979); seu colega Rick Mascitti sugeriu o nome C++ em 1983.45 Em 2018, a National Academy of Engineering concedeu-lhe o Charles Stark Draper Prize – a mais alta honraria da engenharia nos EUA, um prêmio de US$ 500.000 frequentemente chamado de Prêmio Nobel da engenharia – por seu trabalho de projetar e implementar a linguagem de programação C++.9
Fontes
-
“What is the zero-overhead principle?” Standard C++ Foundation FAQ (isocpp.org), mantido com Stroustrup. “What you don’t use, you don’t pay for (in time or space) and further: What you do use, you couldn’t hand code any better.” Veja também Bjarne Stroustrup, “C++ – an Invisible Foundation of Everything,” Overload (ACCU), 2021. ↩↩↩↩↩
-
“C++,” Wikipedia. Enquanto escrevia seu doutorado em Cambridge, Stroustrup usou Simula, mas a achou lenta demais em escala e reescreveu seu simulador em BCPL; ele concluiu que Simula tinha recursos úteis para o desenvolvimento de software de grande porte, mas era lenta demais para uso prático, enquanto BCPL era rápido, mas baixo demais. Relato primário: Bjarne Stroustrup, “A History of C++: 1979–1991,” HOPL-II (artigo do próprio autor). ↩↩↩↩
-
Bjarne Stroustrup, “Quotes,” stroustrup.com (site do próprio autor). “I like my code to be elegant and efficient. The logic should be straightforward to make it hard for bugs to hide, the dependencies minimal to ease maintenance…” e “Code should [be] elegant and efficient; I hate to have to choose between those.” ↩
-
“Bjarne Stroustrup,” Wikipedia. Nasceu em 30 de dezembro de 1950, em Aarhus, na Dinamarca; doutorado pela Universidade de Cambridge em 1979, tese “Communication and control in distributed computer systems”; liderou o departamento de Large-scale Programming Research nos Bell Labs; The C++ Programming Language (1985); membro fundador do comitê de padronização de C++ (ANSI a partir de 1989, ISO a partir de 1991), presidiu o Evolution Working Group; depois Texas A&M (2002–2014), Morgan Stanley (2014–2022), professor titular na Columbia (desde 2022). Veja também a Bio/FAQ de Stroustrup em stroustrup.com. ↩↩↩↩↩↩↩↩
-
Bjarne Stroustrup, “Bjarne Stroustrup’s FAQ,” stroustrup.com. “I wanted to write efficient systems programs in the styles encouraged by Simula67… The specific tasks that caused me to start designing and implementing C++ (initially called ‘C with Classes’) had to do with distributing operating system facilities across a network.” Sobre a renomeação de 1983 por Rick Mascitti: “C++,” Wikipedia. ↩↩↩↩↩
-
“Zero-overhead principle,” cppreference.com. Enuncia o princípio conforme definido por Stroustrup e observa os dois recursos que não o seguem – a identificação de tipo em tempo de execução e as exceções – e que os compiladores comumente incluem chaves para desligá-los. Sobre o projeto multiparadigma e a influência sobre as “zero-cost abstractions” de Rust: “Zero-overhead principle” e a documentação de Rust sobre zero-cost abstractions. ↩↩↩↩↩↩
-
“Resource acquisition is initialization,” Wikipedia. O termo RAII foi cunhado por Stroustrup; a técnica foi desenvolvida para o gerenciamento de recursos seguro contra exceções em C++ durante 1984–1989, principalmente por Stroustrup e Andrew Koenig, e apresentada em seu livro de 1994 The Design and Evolution of C++. A liberação do recurso acontece no destrutor; C++ garante que objetos com duração de armazenamento automática são destruídos ao fim do escopo que os contém, na ordem inversa da construção, dando uma limpeza determinística e segura contra exceções. ↩↩↩↩↩↩
-
Bjarne Stroustrup, The Design and Evolution of C++ (1994), regras de projeto, conforme discutido em “(Re)affirm design principles for future C++ evolution,” artigo P3466R0 do comitê ISO C++. “Leave no room for a lower-level language below C++ (except assembler)” – o raciocínio sendo que, se código mais eficiente pudesse ser escrito em alguma linguagem de nível mais baixo, essa linguagem se tornaria a linguagem de sistemas preferida; para permanecer viável, C++ precisa preservar o acesso direto ao hardware do C, o controle sobre o layout de dados e os tipos primitivos que mapeiam um a um para o hardware. ↩↩↩↩
-
“Bjarne Stroustrup receives Draper Prize, engineering’s top U.S. honor,” Standard C++, 2018: o Charles Stark Draper Prize de 2018, “a $500,000 biannual award… considered the Nobel Prize of engineering,” concedido a Stroustrup “for his work designing and implementing the C++ programming language.” A própria citação da National Academy of Engineering a formula como “for conceptualizing and developing the C++ programming language” (NAE, “Computer Science Pioneer Bjarne Stroustrup to Receive the 2018 Charles Stark Draper Prize for Engineering,” via EurekAlert, 2018). Ele também recebeu a IET Faraday Medal em 2017 por seu trabalho pioneiro em C++. ↩