C++ Versões
O C++ de hoje não é o mesmo de 1998. A linguagem ganha uma versão nova a cada três anos, com recursos que deixam o código mais curto, mais seguro e mais fácil de ler. Ao mesmo tempo, o seu compilador precisa saber qual versão você quer usar, e nem sempre ele escolhe a mais nova sozinho. Nesta aula você vai conhecer as versões, do C++98 ao C++26, entender quem decide o que entra na linguagem e aprender a conferir (e escolher) a versão com que o seu programa é compilado.
- O que é o padrão ISO do C++ e quem decide o que entra nele.
- As versões C++98, 03, 11, 14, 17, 20, 23 e 26, e duas ou três novidades de cada uma.
- A diferença entre o padrão (as regras) e o compilador (o programa que segue as regras).
- Como ver a versão do compilador (
g++ --version) e a versão do C++ em uso (__cplusplus). - Por que o g++ 15 usa o C++17 quando você não pede nada, e por que o guia sempre compila com
-std=c++23. - O que quer dizer o selo C++20 nas aulas.
A ideia: as regras do futebol
As regras do futebol não pertencem a nenhum time. Elas são escritas por uma entidade internacional, mudam de tempos em tempos (o impedimento já mudou várias vezes, o VAR entrou em 2018) e cada campeonato adota as regras novas no seu ritmo. Um campeonato de bairro pode ainda jogar sem VAR, e ninguém diz que aquilo "não é futebol".
Com o C++ é igual:
| No futebol | No C++ |
|---|---|
| O livro de regras | O padrão (standard): um documento que diz o que é C++ válido e o que cada coisa faz. |
| A entidade que escreve as regras | O comitê do C++, dentro da ISO. |
| Uma edição das regras | Uma versão: C++11, C++17, C++23… |
| Os campeonatos que aplicam as regras | Os compiladores: g++, Clang, o compilador da Microsoft (MSVC). |
| Escolher com que regras jogar | A opção -std= do compilador: -std=c++23. |
O padrão ISO
A ISO (International Organization for Standardization, "Organização Internacional de Normalização") é a entidade que publica normas técnicas no mundo inteiro: tamanhos de parafusos, formatos de data, e também linguagens de programação. O C++ é a norma ISO/IEC 14882. Quem escreve essa norma é um grupo de trabalho chamado WG21, o "comitê do C++": centenas de voluntários de empresas (Google, Microsoft, Apple, Intel, Nvidia, bancos, fabricantes de jogos), universidades e pessoas independentes, que se reúnem algumas vezes por ano para discutir e votar propostas.
Isso quer dizer que nenhuma empresa é dona do C++. Qualquer pessoa pode escrever uma proposta. Se o comitê aprovar, ela entra na próxima versão, e os compiladores passam a implementá-la. Desde 2011, o comitê funciona como um trem com horário fixo: a cada três anos sai uma versão, com o que estiver pronto. O que não ficou pronto pega o próximo trem.
O nome de cada versão é o ano em que ela ficou pronta: C++98 é de 1998, C++23 é de 2023. Enquanto uma versão está sendo preparada, os compiladores usam um apelido com letra: o C++23 foi chamado de c++2b, e o C++26 de c++2c. Você ainda vai encontrar esses apelidos em tutoriais e opções de compilador.
O que cada versão trouxe
A tabela mostra as novidades mais marcantes de cada versão. Não se preocupe com os nomes agora: cada um tem a sua aula, e o link leva até ela. Todos os exemplos das aulas foram conferidos com o g++ 15.
| Versão | Apelido | Principais novidades |
|---|---|---|
| C++98 | o primeiro padrão | A biblioteca padrão com a STL: std::vector, std::string, std::map e os algoritmos (std::sort). Templates, exceções e namespaces padronizados. |
| C++03 | a revisão | Só correções do texto do C++98, sem recursos novos para quem programa. Para os compiladores, C++98 e C++03 são praticamente a mesma coisa. |
| C++11 | a grande virada | auto, lambdas, o for de intervalo, nullptr, ponteiros inteligentes (std::unique_ptr), semântica de movimento, threads, enum class. É o começo do "C++ moderno". |
| C++14 | o acabamento | std::make_unique, lambdas genéricas ([](auto x)), separador de dígitos (1'000'000) e números binários (0b1010). |
| C++17 | a caixa de ferramentas | std::optional e std::variant, std::string_view, desestruturação (auto [a, b] = …), std::filesystem para pastas e arquivos, if constexpr. |
| C++20 | a segunda grande virada | Concepts, ranges, std::format, módulos, o operador "nave espacial" <=>, std::span, corrotinas. |
| C++23 | a versão do guia | std::print e std::println, std::expected (um resultado ou um erro), import std; (a biblioteca padrão inteira como módulo), std::ranges::to, std::flat_map. |
| C++26 | a próxima | Reflexão (o programa "olhar para si mesmo" durante a compilação), contratos (pré-condições conferidas pelo compilador), std::execution (tarefas paralelas). Aprovado tecnicamente pelo comitê em março de 2026; os compiladores ainda estão implementando. |
A Ana escreveu um programinha de teste para cada versão, usando as novidades da tabela, e compilou cada um com o -std= da versão. Todos compilaram e rodaram no g++ 15, inclusive alguns recursos pequenos do C++26 (como a variável "descartável" _ e o = delete("motivo")). A reflexão e os contratos do C++26, não: o g++ 15 ainda não os tem. A aula Novidades do C++11 ao C++26 mostra cada recurso com exemplos.
O comitê tem muito cuidado para não "quebrar" programas que já existem: quase todo código C++98 compila sem mudanças com -std=c++23. Mas o contrário não vale: um programa que usa std::println (C++23) não compila com -std=c++17. Por isso o guia marca os recursos novos com um selo e mostra a alternativa antiga.
Padrão × compilador
O padrão é só um documento, com mais de duas mil páginas. Quem transforma o seu código em programa é o compilador, e cada compilador é um projeto separado, com a sua própria numeração de versão:
| Compilador | Comando | De quem | Versão no guia |
|---|---|---|---|
| GCC (GNU Compiler Collection) | g++ | Projeto GNU, software livre | 15.2 (a do Ubuntu 26.04) |
| Clang (projeto LLVM) | clang++ | Comunidade LLVM (Apple, Google e outros), software livre | 21.1 no terminal; 22 no editor do guia |
| MSVC (Microsoft Visual C++) | cl | Microsoft, vem com o Visual Studio | (não usado no guia) |
Não confunda os números: g++ 15 é a versão do programa GCC; C++23 é a versão da linguagem. O g++ 15 entende várias versões da linguagem, do C++98 ao C++26 (este último em parte). Os compiladores implementam as novidades aos poucos, às vezes antes de a versão ficar pronta, às vezes anos depois. O site cppreference tem uma tabela de qual recurso funciona em qual compilador.
Ver a versão do compilador
A opção --version mostra a versão do programa:
$ g++ --version g++ (Ubuntu 15.2.0-16ubuntu1) 15.2.0 « g++ versão 15.2.0, empacotado pelo Ubuntu Copyright (C) 2025 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ clang++ --version Ubuntu clang version 21.1.8 (6ubuntu1) « clang versão 21.1.8 Target: x86_64-pc-linux-gnu « gera programas para PC (x86-64) com Linux Thread model: posix InstalledDir: /usr/lib/llvm-21/bin
O texto em inglês do g++ diz que ele é software livre, sem garantia. O 15.2.0 se lê assim: 15 é a versão principal (uma por ano, com recursos novos), 2 é a revisão (correções), e o último número quase sempre é 0. Repare que o comando g++ --version não diz qual versão do C++ ele usa. Para isso, há outro jeito.
Ver a versão do C++: __cplusplus
Todo compilador define uma "constante" chamada __cplusplus (com dois sublinhados no começo), cujo valor é o ano e o mês da versão do C++ em uso. Um programa pode mostrá-la:
#include <iostream>
int main() {
std::cout << "__cplusplus = " << __cplusplus << "\n";
}
- __cplusplus
- Um nome que o próprio compilador cria (uma macro do pré-processador, aula O Pré-processador). Você não declara nada: ele já existe em todo programa C++.
- 201703
- O valor:
2017é o ano e03o mês da versão. Não é uma data exata de lançamento, é um número combinado no padrão.
A Ana compila sem pedir versão nenhuma, e depois com cada -std=. O for do terminal repete o mesmo comando para cada valor da lista (você não precisa entendê-lo agora):
$ g++ versao.cpp -o versao && ./versao __cplusplus = 201703 « sem -std: o g++ 15 usa o C++17! $ for v in c++98 c++03 c++11 c++14 c++17 c++20 c++23 c++26; do g++ -std=$v versao.cpp -o versao && echo -n "$v: " && ./versao; done c++98: __cplusplus = 199711 c++03: __cplusplus = 199711 « C++03 tem o mesmo número do C++98 c++11: __cplusplus = 201103 c++14: __cplusplus = 201402 c++17: __cplusplus = 201703 c++20: __cplusplus = 202002 c++23: __cplusplus = 202302 « a versão do guia c++26: __cplusplus = 202400 « ainda não terminado no g++ 15: número provisório $ clang++ versao.cpp -o versao && ./versao __cplusplus = 201703 « o Clang 21 também usa C++17 por padrão $ clang++ -std=c++23 versao.cpp -o versao && ./versao __cplusplus = 202302
Este é o ponto mais importante da aula: sem -std, o g++ 15 compila como C++17, uma versão de 2017. Não é o mais novo que ele sabe, é o que os desenvolvedores do GCC consideraram mais seguro como padrão. Na verdade, sem -std ele usa o gnu++17: o C++17 com algumas extensões próprias do GCC (o valor de __cplusplus é o mesmo). Dá para ver o valor sem escrever programa nenhum, pedindo ao pré-processador a lista das macros que ele define:
$ g++ -dM -E -x c++ /dev/null | grep __cplusplus #define __cplusplus 201703L « o L no fim quer dizer "número long"
(O -dM -E lista as macros, o -x c++ diz "trate como C++" e o /dev/null é um arquivo vazio.) O padrão muda com o tempo: o GCC 16, lançado em abril de 2026, passou a usar o C++20 quando você não pede nada. O Ubuntu 26.04 da Ana ainda traz o g++ 15. Por causa dessas diferenças, o guia nunca depende do padrão do compilador.
Por que o guia usa -std=c++23
Muitos recursos que o guia ensina desde o Nível 1 são do C++20 ou do C++23, como o std::println. Sem pedir, eles não funcionam no g++ 15:
#include <print>
int main() {
std::println("Olá, {}!", "Ana");
}
$ g++ print.cpp -o print
print.cpp: In function ‘int main()’:
print.cpp:4:10: error: ‘println’ is not a member of ‘std’
4 | std::println("Olá, {}!", "Ana");
| ^~~~~~~
print.cpp:4:10: note: ‘std::println’ is only available from C++23 onwards
$ g++ -std=c++23 -Wall -Wextra print.cpp -o print && ./print
Olá, Ana!
A primeira tentativa falhou com ‘println’ is not a member of ‘std’ ("println não é membro de std"), e o g++ ainda deixou uma dica (note): "std::println só está disponível a partir do C++23". Com -std=c++23, funcionou. Por isso o comando padrão das aulas é:
g++ -std=c++23 -Wall -Wextra programa.cpp -o programa
O -std=c++23 escolhe a versão; o -Wall -Wextra liga os avisos (aula Avisos). A aula Compilar com g++ explica cada pedaço. As caixas Experimente já compilam com -std=c++23 -Wall -Wextra sozinhas.
Confira no editor do guia. Esta caixa mostra o __cplusplus do compilador do navegador:
Missão: rode e confira que o número é 202302, o do C++23. Depois acrescente uma linha que mostre o ano sozinho: std::cout << __cplusplus / 100 << "\n"; (dividir por 100 "corta" os dois últimos dígitos, o mês). Deve aparecer 2023.
#include <iostream>
int main() {
std::cout << "__cplusplus = " << __cplusplus << "\n";
}
#include <iostream>
int main() {
std::cout << "__cplusplus = " << __cplusplus << "\n";
std::cout << __cplusplus / 100 << "\n";
}
Escolher a versão: as opções -std=
| Opção | Versão | Também aceita | __cplusplus (g++ 15) |
|---|---|---|---|
-std=c++98 | C++98 | 199711 | |
-std=c++03 | C++03 | 199711 | |
-std=c++11 | C++11 | c++0x (apelido antigo) | 201103 |
-std=c++14 | C++14 | c++1y | 201402 |
-std=c++17 | C++17 | c++1z | 201703 |
-std=c++20 | C++20 | c++2a | 202002 |
-std=c++23 | C++23 (a do guia) | c++2b | 202302 |
-std=c++26 | C++26 (parcial no g++ 15) | c++2c | 202400 |
-std=gnu++23 etc. | A mesma versão, com extensões do GCC | igual à versão | |
| (nada) | gnu++17 no g++ 15 e no Clang 21; gnu++20 no GCC 16 | 201703 no g++ 15 |
No compilador da Microsoft, a opção tem outra forma: /std:c++20 ou /std:c++latest (a mais nova que ele conhece); sem nada, o MSVC usa o C++14. A aula Instalar no Windows e macOS mostra onde ela fica no Visual Studio.
O selo de versão do guia
Quando uma aula usa um recurso de uma versão recente, ele aparece com um selo, assim: std::println C++23. O selo quer dizer: "isto só funciona com -std=c++23 ou mais novo". Junto com o selo, a aula mostra a alternativa antiga, para quando você estiver num projeto que usa uma versão mais velha (é muito comum: empresas trocam de versão devagar, e há projetos presos no C++17 ou até no C++11).
| Recurso | Selo | Alternativa antiga |
|---|---|---|
std::println("Olá, {}!", nome); | C++23 | std::cout << "Olá, " << nome << "!\n"; |
std::format("{} anos", idade) | C++20 | std::to_string(idade) + " anos" |
auto [nome, idade] = pessoa; | C++17 | pessoa.first e pessoa.second |
auto total = 0; | C++11 | int total = 0; |
Recursos do C++11 e do C++14 aparecem sem selo na maior parte do guia: eles são tão antigos e tão usados que qualquer compilador atual os aceita, mesmo sem -std.
Veja na prática. A caixa abaixo foi configurada para compilar como C++20 (como se fosse um projeto de empresa ainda nessa versão), e o código usa std::println, que é do C++23:
Missão: rode e veja o erro: neste projeto não existe std::println. Reescreva o programa com a alternativa do C++20: troque o #include <print> por #include <format> e #include <iostream>, e mostre o texto com std::cout << std::format("Olá, {}! Você tem {} anos.\n", nome, idade);.
#include <print>
#include <string>
int main() {
std::string nome = "Ana";
int idade = 29;
std::println("Olá, {}! Você tem {} anos.", nome, idade);
}
#include <format>
#include <iostream>
#include <string>
int main() {
std::string nome = "Ana";
int idade = 29;
std::cout << std::format("Olá, {}! Você tem {} anos.\n", nome, idade);
}
O {} dentro do texto é um "buraco" que o std::format preenche com os valores seguintes, na ordem. A aula std::format e std::print conta tudo.
Quando dá errado
error: ‘println’ is not a member of ‘std’ (ou outro recurso novo "não existe")
Você viu esse erro acima. O que significa: o recurso existe, mas não na versão do C++ que o compilador está usando. Quase sempre é um -std esquecido: sem ele, o g++ 15 usa o C++17. Leia a linha note: logo abaixo do erro: o g++ costuma dizer a partir de qual versão o recurso existe (only available from C++23 onwards).
Como consertar: compile com -std=c++23. Se você não pode mudar a versão (um projeto antigo), use a alternativa antiga.
does not name a type
#include <iostream>
int main() {
auto idade = 29;
std::cout << idade << "\n";
}
$ g++ -std=c++98 auto98.cpp -o auto98
auto98.cpp: In function ‘int main()’:
auto98.cpp:4:10: error: ‘idade’ does not name a type
4 | auto idade = 29;
| ^~~~~
auto98.cpp:5:18: error: ‘idade’ was not declared in this scope
5 | std::cout << idade << "\n";
| ^~~~~
$ g++ -std=c++11 auto98.cpp -o auto98 && ./auto98
29
O que significa: no C++98, o auto tinha outro significado (antigo e inútil), e o compilador não entendeu a linha: "idade não é nome de um tipo". O segundo erro é consequência do primeiro: como a variável não foi criada, na linha 5 "idade não foi declarada neste escopo". Repare que nenhuma das mensagens diz "use C++11": às vezes o compilador não sabe que você quis um recurso novo.
Como consertar: se um código que funciona em todo lugar dá erros estranhos no seu computador, confira o -std. Com -std=c++11 (ou mais novo), o mesmo arquivo compila e mostra 29.
unrecognized command-line option ‘-std=c++99’
$ g++ -std=c++99 versao.cpp -o versao g++: error: unrecognized command-line option ‘-std=c++99’; did you mean ‘-std=c++98’?
O que significa: "opção de linha de comando não reconhecida; você quis dizer -std=c++98?". Não existe C++99 (existe o C99, uma versão da linguagem C). O mesmo erro aparece se você pedir uma versão que o seu compilador é velho demais para conhecer, por exemplo -std=c++23 num g++ 10.
Como consertar: use um dos nomes da tabela. Se o seu compilador não conhece -std=c++23, atualize-o (aulas Instalar no Linux e Instalar no Windows e macOS) ou tente o apelido -std=c++2b: algumas versões mais antigas conheciam o C++23 só por esse nome, antes de ele ficar pronto.
Referência
| Versão | Ano | __cplusplus | Em uma frase |
|---|---|---|---|
| C++98 | 1998 | 199711 | O primeiro padrão, com a STL |
| C++03 | 2003 | 199711 | Correções |
| C++11 | 2011 | 201103 | O C++ moderno: auto, lambdas, smart pointers, move |
| C++14 | 2014 | 201402 | Acabamento do C++11 |
| C++17 | 2017 | 201703 | optional, string_view, desestruturação; padrão do g++ 15 |
| C++20 | 2020 | 202002 | Concepts, ranges, format, módulos; padrão do GCC 16 |
| C++23 | 2023 | 202302 | print, expected, import std; a versão do guia |
| C++26 | 2026 | (provisório) | Reflexão, contratos, std::execution |
| Para saber… | Use |
|---|---|
| a versão do compilador | g++ --version, clang++ --version |
| a versão do C++ dentro do programa | std::cout << __cplusplus; |
a versão do C++ que o g++ usa sem -std | g++ -dM -E -x c++ /dev/null | grep __cplusplus |
| escolher a versão | g++ -std=c++23 … |
Exercícios
1. Quem decide o que entra numa nova versão do C++?
2. Você compila com o g++ 15 sem nenhum -std. Qual versão do C++ está em uso?
3. Qual versão é chamada de "a grande virada", o começo do C++ moderno, com auto, lambdas e ponteiros inteligentes?
4. O comando da versão
Complete o comando que mostra a versão do compilador g++:
5. Escolher o C++23
Complete a opção que manda o g++ compilar como C++23:
6. Ler o __cplusplus
Um programa mostrou __cplusplus = 202002. Com qual versão do C++ ele foi compilado? (responda no formato C++XX)
Resumo
- O C++ é uma norma ISO (14882), escrita pelo comitê WG21; ninguém é dono. Sai uma versão a cada três anos.
- Versões: C++98 (STL), 03 (correções), 11 (a grande virada), 14, 17 (
optional,string_view), 20 (concepts, ranges,format), 23 (print,expected; a do guia) e 26 (reflexão, contratos). - Padrão = as regras; compilador = o programa (g++ 15, Clang 21, MSVC). g++ 15 ≠ C++15.
g++ --versionmostra a versão do compilador;__cplusplusmostra a versão do C++ em uso.- Sem
-std, o g++ 15 usa C++17 (201703). Por isso o guia sempre compila comg++ -std=c++23 -Wall -Wextra. - O selo C++20 marca recursos novos; a aula mostra a alternativa antiga.
- Próximo passo: ter um compilador no seu computador, em Instalar no Linux.