std::string: Text That Manages Itself
On the previous page you saw how smart pointers let an object own a resource and clean it up automatically. std::string is that same idea applied to text: it owns a buffer of characters, grows it when you append, and frees it when the string goes out of scope. You never call new, never count bytes, and never worry about a missing null terminator.
To use it, include <string>. The class lives in the std namespace.
That + operator is doing real work - it allocates a new buffer big enough for both pieces and copies them in. With a raw char* - a plain pointer into a character buffer - you would be reaching for strcpy and strcat and hoping your buffer was large enough. std::string makes that whole class of mistakes disappear.
Building and Joining Strings
You can concatenate with +, but the workhorse for growing a string in place is +=. It appends to the existing buffer instead of producing a brand-new string each time, which matters inside loops.
A common surprise: + needs at least one operand to already be a std::string. Two string literals are just const char*, so "a" + "b" does not compile - there is no operator+ for two raw pointers. Make one of them a string first:
string s = "a" + "b"; // error: can't add two const char*
string s = string("a") + "b"; // fine - left side is a std::string
string s = "a"s + "b"; // fine in C++14+, the "s" literal suffix
Note that last form uses the s suffix from <string> (using namespace std::string_literals;), which turns a literal directly into a std::string.
Reaching Into a String
A std::string behaves like a container of char, so you can index it, loop over it, and ask for pieces of it.
substr(pos, len) returns a brand-new string copied from the original; it does not modify the source. Watch the bounds: word[10] on a 5-character string is undefined behavior - it won't throw, it just reads garbage. If you want a checked access that throws std::out_of_range, use word.at(10) instead of word[10].
Another classic trap: .size() returns an unsigned type (size_t). Writing a backward loop like for (size_t i = word.size() - 1; i >= 0; --i) never ends, because an unsigned i can never go below zero - it wraps around to a huge number. Loop with a signed index or restructure the condition when you need to walk a string in reverse.
Searching and Replacing
find locates a substring or character and returns the starting index. When the target isn't present, it returns the special constant std::string::npos - always compare against that rather than assuming find returns -1.
To change text in place, replace(pos, len, text) swaps a span for new content (which can be a different length), and insert/erase add or remove pieces:
Strings and Numbers
Text and numbers don't convert by themselves - "42" is three characters, not the integer 42. The standard library gives you conversion functions both ways. Use stoi, stod, and friends to parse text into numbers, and to_string to go the other direction.
Two gotchas here. First, stoi("abc") throws std::invalid_argument, so guard untrusted input with a try/catch block. Second, to_string(3.99) gives the full 3.990000 - if you need control over precision and formatting, that's a job for string streams, which is exactly where we head next.
try {
int n = std::stoi(userInput);
} catch (const std::invalid_argument&) {
std::cout << "That wasn't a number.\n";
}
Next: Input and Output
You've been printing strings with cout all along, but reading them back from the user has its own surprises - cin >> name stops at the first space, so a full line like "Ada Lovelace" needs std::getline instead. The next page covers C++ input and output properly: stream operators, reading whole lines, and mixing >> with getline without tripping over leftover newlines.
Frequently Asked Questions
What is the difference between std::string and char* in C++?
std::string is a class that owns and manages its own memory, grows as needed, and cleans up automatically. A char* is just a raw pointer to characters with a terminating '\0' - you manage the buffer, the length, and the lifetime yourself. Prefer std::string for almost everything; it removes whole categories of buffer-overflow and dangling-pointer bugs.
How do you get the length of a string in C++?
Call .size() or its alias .length() on a std::string: name.size() returns the number of characters as a size_t. Both return the same value; size() is the more common style because it matches every other STL container.
How do you convert a string to a number in C++?
Use std::stoi for int, std::stod for double, and similar (stol, stof). Example: int n = std::stoi("42");. These throw std::invalid_argument if the text isn't a number, so wrap them in a try/catch when the input isn't trusted.