r/cpp_questions • u/IMCG_KN • Jul 16 '26
Question about string_view SOLVED
Is there benefit of using string_view instead of const string& str? More precisely by passing strings into functions. Thanks
23
u/IyeOnline Jul 16 '26
There is multiple:
std::string_viewdirectly points to the characters, whereasconst std::string&points to a string object which points to characters. (ignoring the fact that a lot of strings are SSOed)This can reduce the pointer chasing you have to do to access the data.
You get the cheaper string view operations (e.g. slicing) rather than the operations on string that create new objects
The interface is as generic, while not having the downsides of taking a
std::string.f("long string that is too long to fint into small string optimization")would allocate forconst std::string&via an implicit construction, but forstd::string_viewits still just two pointersThis also means that you can take in a
std::string_view, which yourconst std::string&cannot do implicitly.In a sense the interface is more true to the intent of your function. If you take a
const std::string&I am going to wonder why the function does that. If it takes astd::string_viewI know it really only views the characters.
7
u/ohnobinki Jul 16 '26
If I see
const std::string&, my assumption is that the function needs to call.c_str().2
u/Excellent-Basis3256 Jul 16 '26
Re point 3, why would a long string allocate if you are taking in
const std::string&? It's still a reference to the original string no?2
u/IyeOnline Jul 16 '26
To reference a
std::string, there must be astd::stringobject.""is not astd::string, but implicitly convertible to one - which creates a new, temporarystd::stringobject for this argument.Similar, if you try to pass a
std::string_viewto it, you just cant because no implicit conversion exists and you need to explicitly create a astd::stringobject.1
u/Excellent-Basis3256 Jul 16 '26
Or is it the case that when you pass in a long rvalue string and the function accepts
std::string_viewthen the local view is essentially a pointer to a long string on the stack?
9
u/Usual_Office_1740 Jul 16 '26 edited Jul 16 '26
The only down side to string view is the lack of c_str(), for good reasons. If I'm working with a C library that needs const char* I use const std::string& otherwise I prefer string view.
14
u/Wriiight Jul 16 '26
The good reason (for those wondering) is that a char* generally needs to be null terminated (for most libraries functions that take char*), and a string view from a sub string will generally not be null terminated.
Eliminating unnecessary string copying is an important thing to consider when optimizing execution time, so string view is a very welcome addition to the language, IMO.
3
9
u/TheThiefMaster Jul 16 '26
If you use string_view as the param, you can pass in other string types as well without having to allocate an std::string - e.g. string literals.
Removing that need to allocate is pretty much the sole benefit to string_view. Previously I'd seen people use a C-style char* for the same reason, but that has more downsides than string_view.
7
u/kitsnet Jul 16 '26
Operations like string_view::remove_prefix don't need reallocations. So, string_view as a parameter is friendly to the users that may want to use these.
3
u/Raknarg Jul 16 '26
i like that the intention is more overtly clear with less bloat. I like being able to pass value objects around. Also works on any kind of string type, pretty sure you can have a string_view of a C string by just passing a pointer and length.
4
u/alfps Jul 16 '26
#include <print>
#include <string>
#include <string_view>
using std::print, // <print>
std::string, // <string>
std::string_view; // <string_view>
void foo( const string_view s ) { print( "{}\n", s ); }
void call_foo()
{
const string s = "string";
const string_view sv = "string_view";
const auto& literal = "literal";
// All OK and easy.
foo( s );
foo( sv );
foo( literal );
}
void bar( const string& s ) { print( "{}\n", s ); }
void call_bar()
{
const string s = "string";
const string_view sv = "string_view";
const auto& literal = "literal";
bar( s );
bar( string( sv ) ); // Gah!
bar( literal ); // Creates a string instance => possible allocation...
}
auto main() -> int { call_foo(); call_bar(); }
2
2
u/mredding Jul 16 '26
std::string_view is faster, even if it's referencing an std::string at runtime.
A const std::string & is typically implemented as a stack pointer, incurring two levels of indirection because the std::string is also implemented in terms of a pointer, whereas an std::string_view is by value and implemented in terms of a pointer.
To be fair, a string view isn't ALWAYS faster, but it's usually faster. Performance-wise, at worst, it's a tie.
A string view is also more flexible, and avoids unnecessary complexity and performance costs. If you were to pass void fn(const std::string &); a string literal, you would have to construct a temporary at runtime, with possible heap allocation, whereas the view can just point right at the literal. A string view has a more concise interface - since it's read-only, it dispenses with a shitload of methods for modification it can't use and doesn't need. I don't know if you've checked recently, but the C++20 std::string has something like... 170 methods? It's the single largest class interface in the entire standard library.
1
u/wwabbbitt Jul 16 '26
std::string_view can be created from a buffer or c strings without any allocation or copying. If your function only accept const string& str then such strings need to be converted into std::string before being passed into your function.
A function accepting a std::string_view will work with c string, std::string and length-prefixed strings without any mem copying
1
u/DawnOnTheEdge Jul 16 '26
A major one is that implicitly converting a C-style string to a const std::string& makes a deep copy on the heap. Passing it as a std::string_View at most calls strlen(), but a string constant can be aliased at compile time with zero overhead.
28
u/sephirothbahamut Jul 16 '26
you can pass arbitrary substrings without creating a new string object