How Strings Work in C++ (and how to use them)
Video Link: C++ Strings
Playlist Link: C++ Tutorial Playlist by The Cherno
📌 Prerequisites (Mentioned at 0:06)
- It’s helpful to have watched the previous videos on:
🤔 What is a String? (General Concept) (0:21)
- A string is essentially a sequence or group of characters.
- Characters can be:
- Letters (a-z, A-Z)
- Numbers (0-9)
- Symbols (!, @, #, $, %, etc.)
- Basically, a string represents text.
- Representing text is fundamental in programming for user interfaces, file handling, data processing, etc.
💡 How Strings Work: The Basics (1:08)
- To understand strings, you first need to understand how characters work.
- Characters (
char) in C++: (1:53)- The
chardata type is used. - Typically,
charis 1 byte (8 bits) of memory. - This 1-byte size is often used for low-level memory manipulation (like pointer arithmetic in bytes or creating memory buffers).
- The
- Character Encoding: (2:00)
- How characters (letters, symbols) are mapped to numbers (and thus, bytes).
- ASCII is the most basic standard, using 1 byte (technically 7 bits, extended ASCII uses 8). It can represent 256 different characters (0-255).
- This is enough for English letters (uppercase/lowercase), numbers, and common symbols.
- Limitation: ASCII cannot represent characters from many other languages (e.g., Japanese, Chinese, Russian, Korean) because there are far more than 256 unique characters globally. (3:22)
- Other encodings exist (UTF-8, UTF-16, UTF-32 - part of Unicode) to handle this, often using more than 1 byte per character. This video focuses on the basic ASCII/
charconcept.
⛓️ C-Style Strings: Character Pointers & Arrays (2:59)
- Traditionally (in C, and still usable in C++), strings are represented as arrays of characters, often manipulated via pointers.
- String Literals: When you write text in double quotes like
"Cherno", this is a string literal.- Example:
const char* name = "Cherno"; nameis a pointer (char*) pointing to the first character (‘C’) of a sequence of characters stored somewhere in the program’s memory.- This memory location for string literals is often read-only.
- Example:
- Why
const? (5:54)- Because string literals are often in read-only memory, trying to modify them can cause a crash.
- Declaring the pointer as
const char*makes the data pointed to constant (read-only from the perspective of this pointer). This helps prevent accidental modification attempts. - Example of what NOT to do:
char* name = "Cherno"; // Problematic: Assigning literal to non-const pointer name[2] = 'a'; // CRASH! Trying to write to read-only memory.
- Null Termination: (8:07)
- How does the program know where a C-style string ends if it only has a pointer to the start?
- Answer: A special null terminator character (
\0) is automatically added at the end of string literals. - This character has an ASCII value of 0.
- Functions working with C-style strings (like printing) read characters sequentially from the starting address until they encounter this null byte (value 0).
- Memory View:
"Cherno"in memory looks likeC h e r n o \0(represented by their byte values, with the last one being00). (7:21)
- Manual Char Arrays: (8:48)
- You can create strings using explicit char arrays.
- Example (Incorrect - Missing Null Terminator):
// Array size exactly matches visible characters char name2[6] = {'C', 'h', 'e', 'r', 'n', 'o'}; std::cout << name2 << std::endl; // Prints "Cherno" + GARBAGE until a 0 byte is found in memory - Example (Correct - With Null Terminator):
// Array size needs to be N+1 for N characters + null terminator char name2[7] = {'C', 'h', 'e', 'r', 'n', 'o', 0}; // Using integer 0 // OR // char name2[7] = {'C', 'h', 'e', 'r', 'n', 'o', '\0'}; // Using null character literal std::cout << name2 << std::endl; // Prints "Cherno" correctly - Key takeaway: If manually creating char arrays for strings, always allocate one extra byte for the null terminator and ensure it’s set to 0 or
\0.
✨ The C++ std::string Way (11:03)
- C++ provides a much more convenient and safer way to handle strings via the Standard Library.
- Include Header:
#include <string> - Usage:
#include <string> #include <iostream> int main() { std::string name = "Cherno"; // Initialize directly from string literal std::cout << name << std::endl; } - How it Works:
std::stringis a class that manages string data.- Internally, it likely uses a dynamically allocated character array (on the heap).
- It handles memory management (allocation, resizing, deallocation) automatically.
- It automatically manages the null terminator when needed.
- Advantages:
- Easier: Simpler syntax, less manual memory management.
- Safer: Reduces risks of buffer overflows and memory errors common with C-style strings.
- Functionality: Provides many useful member functions (e.g., finding length, appending, searching).
- Concatenation (Appending Strings): (14:08)
- Problem:
std::string name = "Cherno" + " hello!";// ERROR!- Reason: Both
"Cherno"and" hello!"areconst char*(C-style string literals/pointers). C++ doesn’t define how to add twoconst char*pointers together in this context.
- Reason: Both
- Solution 1 (Using
+=):std::string name = "Cherno"; name += " hello!"; // Appends " hello!" to the existing string 'name' std::cout << name << std::endl; // Outputs "Cherno hello!"- This works because
std::stringoverloads the+=operator to acceptconst char*.
- This works because
- Solution 2 (Explicit
std::stringConversion):std::string name = std::string("Cherno") + " hello!"; // Create std::string first std::cout << name << std::endl; // Outputs "Cherno hello!"- This works because
std::string("Cherno")creates astd::stringobject. The+operator is overloaded forstd::string+const char*.
- This works because
- Problem:
- Finding Substrings: (15:14)
- Use the
.find()member function. - Example:
std::string name = "Cherno hello!"; bool contains = name.find("no") != std::string::npos; // std::string::npos is a special static member value indicating "not found" // If name.find("no") returns anything other than npos, "no" was found. if (contains) { std::cout << "Found 'no'!" << std::endl; }
- Use the
- Getting Size/Length: (13:45)
- Use the
.size()member function. - Example:
std::string name = "Cherno"; std::cout << name.size() << std::endl; // Outputs 6 - This is much easier than using C-style functions like
strlen().
- Use the
👉 Passing Strings to Functions (16:13)
- How should you pass
std::stringobjects to functions? - Option 1: Pass by Value (Generally BAD for strings)
void PrintString(std::string str) { // Pass by value std::cout << str << std::endl; } // Calling: PrintString(myString);- Problem: This creates a copy of the entire string every time the function is called.
- Copying involves allocating new memory on the heap and copying all the character data. This is inefficient and slow, especially for long strings or frequent function calls.
- Option 2: Pass by Constant Reference (Usually BEST) 👍
void PrintString(const std::string& str) { // Pass by constant reference // str += "h"; // ERROR: Cannot modify because of 'const' std::cout << str << std::endl; } // Calling: PrintString(myString);&: Passes a reference (an alias to the original string, avoids copying).const: Prevents the function from modifying the original string (makes it read-only within the function scope).- Benefit: Highly efficient (no copying) and safe (prevents accidental modification).
- Rule of Thumb: If a function only needs to read a string, pass it by
const std::string&.
🙏 Conclusion (17:54)
- Strings are fundamental for text representation.
- C-style strings (
char*, char arrays) require manual null termination and careful memory management. - C++
std::stringprovides a safer, easier, and more functional way to work with strings. - Use
std::stringwhenever possible in C++. - Pass strings by
constreference (const std::string&) to functions when you don’t need to modify them, for efficiency. - The video style was more conversational; feedback is welcome.
- Support on Patreon (patreon.com/TheCherno) helps create more content and gives access to community features (Slack/Discord).
For more details on specific std::string functions, consult a C++ reference like cppreference.com.
