Introdução: a batalha eterna das constantes em C++
\n\nSe você já escreveu em C++ (ou mesmo está começando a estudá-lo), certamente já se deparou com const. Este prefixo mágico promete que o valor de uma variável não mudará. Mas então veio o C++11 e trouxe consigo o constexpr. E a confusão começou.
No Stack Overflow, a pergunta "What's the difference between constexpr and const?" acumulou centenas de milhares de visualizações. Programadores de todos os níveis confundem esses dois conceitos, usando-os como sinônimos. Mas isso é um grande erro!
\n\nNeste tutorial, vamos entender de uma vez por todas como constexpr e const diferem em C++. Você aprenderá:
- \n
- O que é uma constante de tempo de compilação e uma constante de tempo de execução. \n
- Por que
constnem sempre é sobre desempenho. \n - Como
constexprtransforma C++ em uma linguagem moderna e segura. \n - Quando usar cada uma dessas construções. \n
Vamos nessa! 🚀
\n\nCapítulo 1. const: uma promessa, não uma garantia
\n\nVamos começar pela base. const em C++ é um qualificador de tipo que diz ao compilador: "Ei, esse valor não pode ser alterado após a inicialização". Parece simples, mas há um detalhe.
Exemplo 1: const em ação
\n\n#include <iostream>\n\nint main() {\n const int x = 42; // Promessa: x não mudará\n // x = 100; // Erro de compilação — ótimo!\n \n std::cout << x; // Exibirá 42\n return 0;\n}\n\nTudo bonito. Mas e se o valor da variável const for calculado apenas em tempo de execução?
Exemplo 2: const que é calculado em runtime
\n\n#include <iostream>\n\nint get_value() {\n return 42; // Função retorna um valor\n}\n\nint main() {\n const int y = get_value(); // Ainda é const?\n // Mas o valor de y só é conhecido em tempo de execução!\n \n // Vamos tentar usar em um array:\n // int arr[y]; // Erro! y não é uma constante de tempo de compilação!\n \n return 0;\n}\n\nAqui está o principal truque! const protege a variável contra alterações, mas não garante que seu valor seja conhecido em tempo de compilação. Se o valor vem de uma função, ele é calculado apenas quando o programa é executado.
Conclusão chave: const é um contrato de imutabilidade, não de calculabilidade em tempo de compilação.
Capítulo 2. constexpr: constantes que vivem no código
\n\nÉ aqui que entra o constexpr. Esse especificador apareceu no C++11 e mudou radicalmente a abordagem das constantes. constexpr significa: "Este valor deve ser calculado em tempo de compilação". Ou, pelo menos, pode ser calculado.
Exemplo 3: variável constexpr
\n\n#include <iostream>\n\nint main() {\n constexpr int z = 42; // Garantia: valor conhecido em compile-time\n \n int arr[z]; // Funciona! z é uma constante de tempo de compilação\n \n std::cout << sizeof(arr) / sizeof(arr[0]); // Exibirá 42\n return 0;\n}\n\nA diferença é óbvia: constexpr permite usar a variável onde o compilador precisa saber o valor exato — por exemplo, para o tamanho de um array ou parâmetros de template.
Exemplo 4: funções constexpr
\n\nMas o mais interessante são as funções. constexpr pode ser aplicado a funções, e então elas podem ser calculadas em tempo de compilação, se todos os argumentos também forem constantes de tempo de compilação.
#include <iostream>\n\nconstexpr int square(int x) {\n return x * x;\n}\n\nint main() {\n constexpr int result = square(5); // Calculado em compile-time!\n int arr[result]; // Funciona\n \n std::cout << result; // 25\n \n int runtime_value =