In C++, when passing a string to a function, it has been common practice to use const std::string& as the argument. However, this method has performance issues. If you try to pass a C-style string literal (e.g., “Hello”) to such a function, a temporary std::string object is created on the spot, causing memory allocation and copying.
The solution to this problem is std::string_view, which was introduced in C++17. string_view is a lightweight, non-owning object that points to a “part” or “all” of existing string data.
In this article, I will explain how string_view prevents unnecessary string copying and improves code performance.
What is C++17?
C++17 is a standard of the C++ language that was finalized in 2017. Since std::string_view was introduced in C++17, you need a compiler that supports C++17 to use it.
Sample Code Using string_view
This code defines a function that cuts out and displays a part of a string in two ways: one using the traditional const string& and the other using string_view. This demonstrates the difference in how they are used.
#include <iostream>
#include <string>
#include <string_view> // Required to use string_view
using namespace std;
// Function using traditional const string&
void printSubstring_String(const string& s) {
cout << s.substr(0, 5) << endl;
}
// Function using C++17 string_view
void printSubstring_StringView(string_view sv) {
cout << sv.substr(0, 5) << endl;
}
int main() {
string my_string = "Hello, Modern C++";
const char* c_style_string = "This is a C-style string";
cout << "--- Using const string& ---" << endl;
// Passing a string -> No copy occurs
printSubstring_String(my_string);
// Passing a C-style string -> Temporary string object created, copy occurs
printSubstring_String(c_style_string);
cout << "\n--- Using string_view ---" << endl;
// Passing a string -> No copy occurs
printSubstring_StringView(my_string);
// Passing a C-style string -> No copy occurs
printSubstring_StringView(c_style_string);
// Passing a string_view -> Of course, no copy occurs
printSubstring_StringView(string_view{"This is a string_view literal"});
return 0;
}
Code Explanation
void printSubstring_String(const string& s)
When you pass the C-style string c_style_string to this traditional function, a temporary std::string object is created on the spot to match the const string& argument type. At this time, memory allocation to store the string “This is a C-style string” and character copying occur.
void printSubstring_StringView(string_view sv)
This new function accepts string_view as an argument. string_view can be constructed from std::string or C-style string literals without copying.
printSubstring_StringView(my_string): Thestring_viewpoints directly to the internal buffer ofmy_string.printSubstring_StringView(c_style_string): Thestring_viewpoints directly to the memory address ofc_style_string.
In either case, no new memory allocation or string copying occurs. string_view is a very lightweight object that only holds a pointer and length information.
Cautions When Using string_view
string_view is merely a “view” of an existing string and does not own the data. Therefore, if the original string pointed to by string_view is destroyed before the string_view, it becomes a “dangling” reference. Accessing it in this state causes undefined behavior.
Summary
In this article, I explained how to use std::string_view in C++17 to avoid unnecessary string copying and improve performance.
std::string_viewis a read-only view that does not own the string.- By changing function arguments from
const std::string&tostd::string_view, you can accept various types of strings without copy costs. - You must always pay attention to the lifetime of the original string being pointed to.
In conclusion, if a function argument does not require ownership of the string and only needs to read it, using std::string_view instead of const std::string& is the best practice in modern C++.
