std::string and String Manipulation
In C++, std::string is the standard library class for storing and manipulating text. Unlike C-style character arrays (which require manual memory management and null-termination), std::string handles its own memory automatically, grows on demand, and provides a rich set of member functions for searching, slicing, comparing, and modifying text. You should use std::string whenever you need to work with text in modern C++ — raw character arrays are a C API concern, not an everyday tool.
Creating strings
A std::string can be constructed from a string literal, from another string, from repeated characters, or left empty. The #include <string> header is required (though it is often pulled in transitively by other headers).
#include <string>
std::string empty; // empty string ""
std::string name = "Alice"; // from string literal
std::string greeting("Hello"); // direct construction
std::string copy = name; // copy of name
std::string repeated(5, 'x'); // "xxxxx" — 5 copies of 'x'
std::cout << name.size(); // 5 — number of characters
std::cout << name.length(); // 5 — same as size()
std::cout << name.empty(); // 0 (false) — true only if size() == 0Concatenation and modification
The + operator concatenates two strings into a new string. The += operator appends to the end in place. Individual characters are accessed and modified with the [] operator or the bounds-checked at() method.
std::string first = "Hello";
std::string space = " ";
std::string last = "World";
std::string full = first + space + last; // "Hello World"
full += "!"; // "Hello World!"
// Individual characters (0-indexed):
char c = full[0]; // 'H'
full[0] = 'h'; // "hello World!"
// at() throws std::out_of_range if index is invalid:
char safe = full.at(0); // 'h'
// Iterating characters:
for (char ch : full) {
std::cout << ch;
}
// Using indices:
for (std::size_t i = 0; i < full.size(); ++i) {
full[i] = std::toupper(full[i]);
}Comparison
std::string supports all comparison operators (==, !=, <, >, etc.) with lexicographic (dictionary) ordering. Unlike C-style strings, you do not need strcmp — just use ==.
std::string a = "apple"; std::string b = "banana"; if (a == b) std::cout << "equal"; if (a != b) std::cout << "not equal"; // prints this if (a < b) std::cout << "a comes first"; // true: 'a' < 'b' // Compare with a literal directly: if (a == "apple") std::cout << "yes"; // fine — literal is converted
Searching and substrings
find() returns the index of the first occurrence of a substring, or std::string::npos (a special large value) if not found. substr(pos, len) extracts a portion of the string.
std::string sentence = "the quick brown fox";
// find — returns index or npos:
std::size_t pos = sentence.find("quick");
if (pos != std::string::npos) {
std::cout << "Found at index " << pos; // Found at index 4
}
// substr(start_position, length):
std::string word = sentence.substr(4, 5); // "quick"
std::string rest = sentence.substr(4); // "quick brown fox" (to end)
// Replace a portion:
sentence.replace(4, 5, "slow"); // "the slow brown fox"
// Check prefix/suffix (C++20):
// sentence.starts_with("the") → true
// sentence.ends_with("fox") → trueConverting between strings and numbers
The standard library provides free functions for converting numbers to strings and strings to numbers. std::to_string() converts any arithmetic type to a string. The stoi, stod, and similar functions parse a string and return the numeric value.
#include <string>
// Number to string:
int n = 42;
std::string s = std::to_string(n); // "42"
double d = 3.14;
std::string t = std::to_string(d); // "3.140000"
// String to number (throws std::invalid_argument or std::out_of_range on error):
int parsed = std::stoi("123"); // 123
double fp = std::stod("3.14"); // 3.14
long long big = std::stoll("9999999999"); // long long versionFor formatted output (e.g., 2 decimal places), prefer std::format (C++20) or std::ostringstream over std::to_string.
Quick reference
| Operation | Code |
|---|---|
| Length | s.size() or s.length() |
| Empty check | s.empty() |
| Access character | s[i] or s.at(i) (bounds-checked) |
| Append string | s += other or s.append(other) |
| Append character | s += 'x' or s.push_back('x') |
| Concatenate | s + t (produces new string) |
| Find substring | s.find(sub) → index or npos |
| Extract substring | s.substr(pos, len) |
| Replace portion | s.replace(pos, len, replacement) |
| Clear contents | s.clear() |
| Remove characters | s.erase(pos, len) |
| Insert text | s.insert(pos, text) |
| First character | s.front() |
| Last character | s.back() |
| C-string pointer | s.c_str() (for C APIs) |
Key rules to remember
Use std::string instead of char arrays for all text in modern C++
std::string manages memory automatically, prevents buffer overflows, and provides a rich API. char arrays are a C legacy.
Pass std::string by const reference to avoid expensive copies
void f(const std::string& s) avoids copying the string's internal buffer. Pass by value only if the function needs its own copy.
Check find() result against std::string::npos before using it
If the substring is not found, find() returns npos (a very large number). Using it as an index causes undefined behavior.
std::string operator[] does not bounds-check — use at() when the index might be out of range
s[i] is undefined behavior if i >= s.size(). s.at(i) throws std::out_of_range instead.