In C++, strings are handled through std::string in the standard library, with a compact set of methods that enable efficient construction, searching, modification, and conversion. This reference explains the most commonly used string methods, their behavior, and their performance characteristics, focusing on safe and predictable usage across modern C++ standards. You will learn when each method is appropriate, how to avoid common pitfalls, and how these methods fit into broader text-processing workflows. The guidance emphasizes correctness, clarity, and efficiency, making it suitable for both learning and day-to-day professional development.
Core Construction and Assignment
Default Construction and Initialization
Strings can be default-constructed, copy-constructed, moved, or assigned from C-style arrays and literals. Prefer std::string s{"hello"} or std::string s = "hello" for clarity. Move semantics since C++11 avoid unnecessary copies when passing or returning strings. For sizing behavior, std::string s{n} creates a string of n repeated characters, while std-string{n, c} fills with character c. Prefer in-place construction when possible to reduce temporaries, and be aware that small string optimization (SSO) can avoid dynamic allocations for short texts.
std::string()— empty string, typically SSO-capablestd::string(size_type n, char c)— n copies of cstd::string(const char* s)— from C-string, requires allocation unless SSO sufficesstd::string(const std::string& other)— copy; may copy data or share on write in pre-C++11 implementationsstd::string(std::string&& other)— move; usually constant time
Assignment Operators and Swap
Copy assignment s = other replaces contents, with self-assignment being safe but potentially redundant. Move assignment s = std::move(other) transfers ownership of resources and leaves the source in a valid but unspecified state. swap(a, b) exchanges contents in constant time and is noexcept; prefer using std::swap to enable ADL. Self-assignment checks are unnecessary for move assignment but can be kept for readability in complex code bases.
Capacity and Information Queries
Size, Length, and Empty Checks
s.size() and s.length() return the number of characters; they are equivalent and constant time. Use s.empty() to test zero size; it is clearer and may be more aggressively optimized than s.size() == 0 or s.size() == 0. Note that size is measured in characters, not bytes, which matters for non-ASCII encodings. s.max_size() indicates theoretical capacity limits imposed by allocator and implementation.
Reserve, Capacity, and Shrink-to-Fit
s.reserve(new_cap) ensures sufficient storage to avoid reallocation until at least new_cap characters are stored. It never shrinks capacity. s.capacity() reports allocated storage; capacity is always greater than or equal to size. Use reserve when building large strings in loops to minimize reallocations. s.shrink_to_fit() is a non-binding request to reduce capacity to match size; it may be ignored by the implementation.
| Method | Verified Detail | Source Type |
|---|---|---|
empty() |
Returns true if size is 0; constant time | ISO C++ Standard |
size() / length() |
Character count; equivalent and noexcept | ISO C++ Standard |
capacity() |
Allocated storage; >= size | ISO C++ Standard |
reserve(n) |
Ensures capacity >= n; never shrinks | ISO C++ Standard |
shrink_to_fit() |
Non-binding request to fit capacity to size | ISO C++ Standard |
Element Access and Safety
At, Brackets, and Data Pointers
s.at(pos) performs bounds-checked access and throws std::out_of_range on invalid positions; use when safety is required. s[pos] provides unchecked access and does not bounds-check; defaulting to at during development can catch off-by-one errors. s.data() returns a pointer to the internal array (const in C++17 and later). s.c_str() returns a null-terminated C-style string pointer, guaranteed to match data() plus a terminating null. For reading, front() and back() return references to the first and last characters, respectively, and require non-empty strings to avoid undefined behavior.
Operator[] vs. at: Safety and Performance
When performance is critical and indices are known to be in range, operator[] avoids bounds-check overhead. In debug builds or defensively coded modules, at provides meaningful exceptions and clearer intent. Prefer data() or c_str() when passing strings to C APIs; note that prior to C++17, data() was not guaranteed null-terminated for copies, though writes through that pointer resulted in undefined behavior.
Searching and Finding
Find, Rfind, and Find First Of
s.find(args...) locates the first occurrence of a substring or character, returning npos if not found. s.rfind(...) searches backward from the end. s.find_first_of(...) finds any character from a set; s.find_last_of(...) finds the last such character. All find methods accept position and count parameters to limit search scope. Use npos consistently in comparisons; it is usually the largest value of size_type.
Starts With, Ends With, and Contains
Since C++20, s.starts_with(prefix), s.ends_with(suffix), and s.contains(str) provide readable, explicit checks. Before these, emulate starts-with by comparing substrings with compare at position 0, and ends-with by adjusting positions and lengths. These newer methods reduce off-by-one errors and make intent clear; they are constexpr where the arguments are constexpr, enabling compile-time evaluation when possible.
Modification and Transformation
Insert, Erase, and Replace
s.insert(pos, arg) inserts content at a position, returning a reference to *this. Overloads accept strings, C-strings, counts, and iterators. s.erase(pos, len) removes characters and returns a reference; s.erase(iterator) removes a single character. s.replace(pos, len, arg) substitutes a region with new content; all support iterator-range forms. These methods return *this and can throw exceptions; strong exception safety can be managed by working on copies when necessary.
Append and Push Back
s.append(args...) adds content to the end; variants accept strings, C-strings, counts, and ranges. s.push_back(c) adds a single character. For building strings incrementally, consider += or append, and reserve ahead of known growth to avoid repeated reallocations. s.clear() removes all characters but does not necessarily reduce capacity.
Conversion, Extraction, and Utilities
Substr, Copy, and Format
s.substr(pos, len) returns a new string; defaults provide suffix extraction. It may allocate, so use when you need an independent string object. std::copy(s.begin(), s.end(), out) or range-based construction can duplicate content into another container. C++20 introduces std::format for building formatted strings; combine with string views for zero-copy assembly when formatting is required. Prefer string_view for read-only, non-owning access to substrings to avoid allocations.
Numeric Conversions and C Interop
For conversions, use library functions or from_chars when available: std::to_chars writes to character buffers without allocations and sets ec on error. For legacy code, std::stoi, std::stol, and std::stoull parse numbers and throw on errors. When interfacing with C, c_str() supplies a null-terminated buffer; avoid writing through it in C++17 and later. When necessary, copy data into a mutable buffer instead.
Best Practices and Performance Notes
Use reserve when growing strings in loops to achieve linear complexity. Prefer string_view for read-only, non-owning parameter passing to avoid unnecessary copies. Favor at in safety-critical contexts and [] only after profiling and validating bounds. Use C++20 convenience methods like starts_with and contains for clearer intent. Be mindful that non-ASCII text requires encoding-aware handling; std::string stores bytes, and operations are position-based, not code-point-based.
Choose construction and assignment forms that leverage move semantics and SSO. Iterate with care over characters when internationalization is a concern, and prefer standard algorithms over manual loops where possible. These practices help keep string handling efficient, safe, and maintainable across evolving C++ standards.