C++Foundations

C++ Strings & Text: string_view, std::format, std::print, Unicode & Custom Formatters (C++23)

TT
TopicTrick Team
C++ Strings & Text: string_view, std::format, std::print, Unicode & Custom Formatters (C++23)

C++ Strings & Text: string_view, std::format, std::print, Unicode & Custom Formatters (C++23)


Table of Contents


std::string Internals: SSO and Heap Allocation

std::string uses Small String Optimization (SSO): strings up to ~15 bytes (implementation-defined) are stored in the stack portion of the string object itself — zero heap allocation:

cpp

std::string_view: Zero-Copy String Observation

std::string_view is a non-owning, read-only reference to a character sequence. It holds a pointer + length — no allocation, no copy:

cpp

string_view Pitfalls: Lifetime and Null Termination

cpp

std::format: Modern Type-Safe Formatting (C++20)

std::format provides Python/Rust-style format strings with compile-time format string validation:

cpp

Format Specifiers: Alignment, Precision & Fill

cpp

std::print and std::println: Direct Output (C++23)

std::print (C++23) combines formatting and output — thread-safe, faster than cout, safer than printf:

cpp

Custom std::formatter Specialization

Make your own types work with std::format and std::print:

cpp

std::from_chars and std::to_chars: Zero-Allocation Conversion

std::from_chars/std::to_chars are the fastest string-number conversion functions in C++ — no allocation, no locale, no exceptions:

cpp

Frequently Asked Questions

When should I use string_view vs const string&? Use std::string_view when the function only reads the string and the caller might be passing a literal, const char*, or part of a string. Use const std::string& when you need null termination (e.g., passing to a C API that requires it) or when you need guaranteed std::string operations like .c_str(). In new code, prefer string_view — it's strictly more flexible.

Is std::format slower than printf at runtime? For constant format strings, std::format validates the format at compile time and has runtime performance comparable to or better than printf. For dynamic format strings, std::vformat has overhead. In benchmarks, std::print is consistently faster than std::cout formatted output because it avoids std::ios synchronization. Fastest is always std::to_chars + write() for number formatting.

How do I handle UTF-8 strings in C++? C++ doesn't natively understand Unicode grapheme clusters. The practical approach: use std::string as a container of raw UTF-8 bytes (correct — UTF-8 strings are valid byte sequences), use a library like ICU or utfcpp for grapheme-aware operations, and use std::format / std::print which handle UTF-8 output correctly on modern terminals.


Key Takeaway

Modern C++ text handling is categorized by ownership: std::string owns, std::string_view observes. For output, the 2026 standard is std::print/std::println — type-safe, fast, thread-safe. For numeric conversion, from_chars/to_chars are the zero-overhead workhorses. Custom std::formatter specializations make your types first-class citizens in the entire formatting ecosystem.

Read next: STL Containers Deep Dive: vector, map, unordered_map →


Part of the C++ Mastery Course — 30 modules from modern C++ basics to expert systems engineering.