Ready to practice?
Sign up to access interactive coding exercises and track your progress.
Using std::string_view
Pass string data efficiently without copying using lightweight string views.
Introduction to std::string_view
Consider the following program:
#include <iostream>
int main()
{
int score { 1500 }; // score makes a copy of its initializer
std::cout << score << '\n';
return 0;
}
When the definition for score is executed, the initialization value 1500 is copied into the memory allocated for variable int score. For fundamental types, initializing and copying a variable is fast.
Now consider this similar program:
#include <iostream>
#include <string>
int main()
{
std::string message { "Welcome, adventurer!" }; // message makes a copy of its initializer
std::cout << message << '\n';
return 0;
}
When message is initialized, the C-style string literal "Welcome, adventurer!" is copied into memory allocated for std::string message. Unlike fundamental types, initializing and copying a std::string is slow.
In the above program, all we do with message is print the value to the console, and then message is destroyed. We've essentially made a copy of "Welcome, adventurer!" just to print and then destroy that copy. That's inefficient.
We see something similar in this example:
#include <iostream>
#include <string>
void displayMessage(std::string text) // text makes a copy of its initializer
{
std::cout << text << '\n';
}
int main()
{
std::string message { "Welcome, adventurer!" }; // message makes a copy of its initializer
displayMessage(message);
return 0;
}
This example makes two copies of the C-style string "Welcome, adventurer!": one when we initialize message in main(), and another when we initialize parameter text in displayMessage(). That's a lot of needless copying just to print a string!
std::string_view C++17
To address the issue with std::string being expensive to initialize (or copy), C++17 introduced std::string_view (which lives in the <string_view> header). std::string_view provides read-only access to an existing string (a C-style string, a std::string, or another std::string_view) without making a copy. Read-only means that we can access and use the value being viewed, but we can not modify it.
The following example is identical to the prior one, except we've replaced std::string with std::string_view.
#include <iostream>
#include <string_view> // C++17
// text provides read-only access to whatever argument is passed in
void displayMessage(std::string_view text) // now a std::string_view
{
std::cout << text << '\n';
}
int main()
{
std::string_view message { "Welcome, adventurer!" }; // now a std::string_view
displayMessage(message);
return 0;
}
This program produces the same output as the prior one, but no copies of the string "Welcome, adventurer!" are made.
When we initialize std::string_view message with C-style string literal "Welcome, adventurer!", message provides read-only access to "Welcome, adventurer!" without making a copy of the string. When we pass message to displayMessage(), parameter text is initialized from message. This allows us to access "Welcome, adventurer!" through text, again without making a copy of the string.
Prefer `std::string_view` over `std::string` when you need a read-only string, especially for function parameters.
std::string_view can be initialized with many different types of strings
One of the neat things about a std::string_view is how flexible it is. A std::string_view object can be initialized with a C-style string, a std::string, or another std::string_view:
#include <iostream>
#include <string>
#include <string_view>
int main()
{
std::string_view greeting1 { "Welcome, adventurer!" }; // initialize with C-style string literal
std::cout << greeting1 << '\n';
std::string message { "Welcome, adventurer!" };
std::string_view greeting2 { message }; // initialize with std::string
std::cout << greeting2 << '\n';
std::string_view greeting3 { greeting2 }; // initialize with std::string_view
std::cout << greeting3 << '\n';
return 0;
}
std::string_view parameters will accept many different types of string arguments
Both a C-style string and a std::string will implicitly convert to a std::string_view. Therefore, a std::string_view parameter will accept arguments of type C-style string, a std::string, or std::string_view:
#include <iostream>
#include <string>
#include <string_view>
void displayMessage(std::string_view text)
{
std::cout << text << '\n';
}
int main()
{
displayMessage("Welcome, adventurer!"); // call with C-style string literal
std::string quest { "Find the ancient sword" };
displayMessage(quest); // call with std::string
std::string_view hint { quest };
displayMessage(hint); // call with std::string_view
return 0;
}
std::string_view will not implicitly convert to std::string
Because std::string makes a copy of its initializer (which is expensive), C++ won't allow implicit conversion of a std::string_view to a std::string. This is to prevent accidentally passing a std::string_view argument to a std::string parameter, and inadvertently making an expensive copy where such a copy may not be required.
However, if this is desired, we have two options:
- Explicitly create a
std::stringwith astd::string_viewinitializer (which is allowed, since this will rarely be done unintentionally) - Convert an existing
std::string_viewto astd::stringusingstatic_cast
The following example shows both options:
#include <iostream>
#include <string>
#include <string_view>
void processString(std::string text)
{
std::cout << text << '\n';
}
int main()
{
std::string_view message { "Welcome, adventurer!" };
// processString(message); // compile error: won't implicitly convert std::string_view to a std::string
std::string quest { message }; // okay: we can create std::string using std::string_view initializer
processString(quest); // and call the function with the std::string
processString(static_cast<std::string>(message)); // okay: we can explicitly cast a std::string_view to a std::string
return 0;
}
Assignment changes what the std::string_view is viewing
Assigning a new string to a std::string_view causes the std::string_view to view the new string. It does not modify the prior string being viewed in any way.
The following example illustrates this:
#include <iostream>
#include <string>
#include <string_view>
int main()
{
std::string playerName { "Marcus" };
std::string_view nameView { playerName }; // nameView is now viewing playerName
std::cout << nameView << '\n'; // prints Marcus
nameView = "Sarah"; // nameView is now viewing "Sarah" (does not change playerName)
std::cout << nameView << '\n'; // prints Sarah
std::cout << playerName << '\n'; // prints Marcus
return 0;
}
In the above example, nameView = "Sarah" causes nameView to now view the string "Sarah". It does not change the value held by playerName (which is still "Marcus").
Literals for std::string_view
Double-quoted string literals are C-style string literals by default. We can create string literals with type std::string_view by using a sv suffix after the double-quoted string literal. The sv must be lower case.
#include <iostream>
#include <string> // for std::string
#include <string_view> // for std::string_view
int main()
{
using namespace std::string_literals; // access the s suffix
using namespace std::string_view_literals; // access the sv suffix
std::cout << "quest\n"; // no suffix is a C-style string literal
std::cout << "reward\n"s; // s suffix is a std::string literal
std::cout << "item\n"sv; // sv suffix is a std::string_view literal
return 0;
}
Tip: The sv suffix lives in the namespace std::literals::string_view_literals. We recommend using namespace std::string_view_literals, which imports only the literals for std::string_view. This is one of the exception cases where using an entire namespace is generally okay. Avoid such using-directives outside of functions in header files.
It's fine to initialize a std::string_view object with a C-style string literal (you don't need to initialize it with a std::string_view literal).
Advanced note: std::string_view literals are actually C-style string literals in disguise, so initializing a std::string_view using a std::string_view literal won't cause problems.
constexpr std::string_view
Unlike std::string, std::string_view has full support for constexpr:
#include <iostream>
#include <string_view>
int main()
{
constexpr std::string_view greeting { "Welcome, adventurer!" }; // greeting is a string symbolic constant
std::cout << greeting << '\n'; // greeting will be replaced with "Welcome, adventurer!" at compile-time
return 0;
}
This makes constexpr std::string_view the preferred choice when string symbolic constants are needed.
Summary
- std::string_view (C++17) provides read-only access to an existing string without making a copy
- Performance: Avoids expensive string copies that
std::stringmakes during initialization and parameter passing - Flexibility: Can be initialized with C-style strings,
std::string, or anotherstd::string_view - Function parameters:
std::string_viewparameters accept C-style strings,std::string, andstd::string_viewarguments via implicit conversion - No implicit conversion to std::string:
std::string_viewwon't automatically convert tostd::stringto prevent accidental expensive copies - Explicit conversion: Create
std::stringfromstd::string_viewusing explicit initialization orstatic_cast - Assignment: Assigning a new string to a
std::string_viewchanges what it views, but doesn't modify the original string - String literals: Use the
svsuffix to createstd::string_viewliterals (e.g.,"text"sv); requiresusing namespace std::string_view_literals - constexpr support: Unlike
std::string,std::string_viewhas full constexpr support, making it ideal for compile-time string constants
std::string_view is the preferred way to pass strings to functions when you only need read-only access. It avoids expensive copies while maintaining flexibility to accept different string types.
We will continue discussing std::string_view in the next lesson.
Using std::string_view - Quiz
Test your understanding of the lesson.
Practice Exercises
Introduction to std::string_view
Practice using std::string_view for efficient string access.
Lesson Discussion
Share your thoughts and questions
No comments yet. Be the first to share your thoughts!