Introdução: A eterna questão "std::string para int"
\n\nOlá, colega programador! Se você já escreveu em C++ um parser de configurações, processou entrada do usuário ou extraiu números de um arquivo CSV, certamente já enfrentou a tarefa: "Como transformar uma string comum (std::string) em um número inteiro (int)?". Parece simples, não é? No entanto, ao olhar no Stack Overflow, você verá milhares de votos e dezenas de respostas diferentes. Por quê? Porque por trás dessa pergunta simples existe um mundo de compromissos entre conveniência, segurança e desempenho.
Neste artigo, não vamos dar apenas uma resposta seca. Vamos promover uma verdadeira batalha entre os principais métodos de conversão: std::stoi, std::from_chars (C++17), std::stringstream, o bom e velho atoi e até mesmo criar nossa própria solução caseira. Você descobrirá qual método escolher para um servidor de alta carga e qual usar para um protótipo rápido. Vamos nessa!
Método 1: O clássico — std::stoi (C++11)
\n\nA partir do C++11, a biblioteca padrão ganhou a elegante função std::stoi. Ela é simples, legível e lança exceções em caso de erros. É a escolha de 90% dos desenvolvedores para tarefas do dia a dia.
#include <iostream>\n#include <string>\n\nint main() {\n std::string number_str = "12345";\n try {\n int value = std::stoi(number_str);\n std::cout << "Número: " << value << std::endl;\n } catch (const std::invalid_argument& e) {\n std::cerr << "Erro: a string não contém um número!" << std::endl;\n } catch (const std::out_of_range& e) {\n std::cerr << "Erro: o número está fora dos limites do int!" << std::endl;\n }\n return 0;\n}\n\nPrós e contras do std::stoi
\n- \n
- Prós: Simplicidade, suporte a locales (reconhece vírgulas como separadores), tratamento automático de erros via exceções. \n
- Contras: Exceções são caras. Se você estiver parseando milhões de números em um loop, o
try-catchpode desacelerar significativamente o código. \n
Método 2: Mais rápido que o vento — std::from_chars (C++17)
\n\nSe você está escrevendo uma aplicação de alta carga, onde cada nanossegundo conta, então std::from_chars é seu herói. Esta função não aloca memória, não lança exceções e não depende de locale. Ela simplesmente converte caracteres em um número e retorna um ponteiro para o ponto de parada.
#include <iostream>\n#include <charconv>\n#include <string>\n#include <system_error>\n\nint main() {\n std::string number_str = "98765";\n int value = 0;\n auto [ptr, ec] = std::from_chars(number_str.data(), \n number_str.data() + number_str.size(), \n value);\n if (ec == std::errc()) {\n std::cout << "Número: " << value << std::endl;\n } else {\n std::cerr << "Erro de conversão!" << std::endl;\n }\n return 0;\n}\n\nPor que from_chars é o rei do desempenho?
\n- \n
- Zero-overhead: Sem exceções, sem alocações ocultas. \n
- Localização desativada: Não há necessidade de perder tempo verificando separadores decimais. \n
- Retorna o restante da string: Ideal para parsing de colunas em CSV. \n
De acordo com benchmarks, from_chars pode ser de 2 a 10 vezes mais rápido que stoi, especialmente em strings curtas.
Método 3: Artilharia pesada — std::stringstream
\n\nMuitos programadores iniciantes usam std::stringstream para conversão. É uma ferramenta poderosa, mas para a tarefa "string para número", ela é exagerada, como um tanque para ir ao mercado comprar pão.
#include <sstream>\n#include <string>\n#