std::string_view
A std::string_view
pointer to a contiguous character sequence and the length (or end pointer).
It avoids unnecessary heap allocation by not taking ownership.
Much like juce::StringRef
but with added functionality.
Even with copy elision the following example does 3 string copies.
std::string fromFirstOccurrenceOf (const std::string& content,
const std::string& target)
{
return content.substr (content.find (target));
}
std::string text {"Hello Amazing Programming Environment"};
auto subString = fromFirstOccurrenceOf (text, "Prog");
std::cout << subString << '\n';
With std::string_view
only one allocation takes place.
std::string_view fromFirstOccurrenceOf (std::string_view content,
std::string_view target)
{
return content.substr (content.find (target));
}
std::string text {"Hello Amazing Programming Environment"};
auto subString = fromFirstOccurrenceOf (text, "Prog");
std::cout << subString << '\n';
Different character widths are available through template specializations of std::basic_string_view
. As with std::string
and std::basic_string
.
using std::string_view = std::basic_string_view<char>
using std::wstring_view = std::basic_string_view<wchar_t>
using std::u8string_view = std::basic_string_view<char8_t> // (C++20)
using std::u16string_view = std::basic_string_view<char16_t>
using std::u32string_view = std::basic_string_view<char32_t>
juce::StringRef
uses the selected character encoding type to determine the width.
constexpr basic_string_view() noexcept;
constexpr basic_string_view (const basic_string_view& other) noexcept = default;
constexpr basic_string_view (const CharT* s, size_type count);
constexpr basic_string_view (const CharT* s);
Also by using a conversion from std::string
. Or by using the ""sv
literal (in std::literals
).
using namespace std::literals;
constexpr auto text = "Heya, World!"sv;
Almost the same as all non-mutable string operations.
All of the methods (except for copy()
, operator<<
, and std::hash
specialisation) are constexpr
.
Some interesting methods remove_prefix()
, remove_suffix()
, starts_with()
, ends_with()
, iterators…
substr()
is O(1) instead of O(n) for the std::string
equivalent.
"\0"
is not necessarily present in std::string_view
.
Problem with all C-string functions. If a function accepts only a const char*
parameter, it’s probably not safe to pass a std::string_view
, e.g. std::basic_ostream::operator<<
.
Since std::string_view
doesn’t own the memory, the objects lifetime should never exceed the lifetime of the string-owning object.
Crucial when:
std::string_view
from a functionstd::string_view
in objects and containersIf the view is empty, you’ll get undefined behaviour with operator[]
, front()
, back()
, data()
.
So when uncertain, check with empty()
.
When replacing a const std::string&
with a std::string_view
lifetime extension is lost.
std::string createTemporary() { return {}; }
std::string_view nonExtended = createTemporary();
const std::string& extended = createTemporary();
std::string
from a std::string_view
struct UserName
{
std::string name;
UserName (const std::string& name) : name (name) {}
};
UserName u1 {"John With Very Long Name"}; // from const char*
std::string s2 {"Marc With Very Long Name"}; // from lvalue
UserName u2 { s2 };
td::string s3 {"Marc With Very Long Name"}; // from rvalue
UserName u3 { std::move (s3) };
std::string GetString() { return "some string..."; }
UserName u4 { GetString() }; // from return
input parameter | const std::string& |
std::string_view |
std::string & move |
---|---|---|---|
const char* |
2 allocations | 1 allocation | 1 allocation + move |
const char* SSO |
2 copies | 1 copy | 2 copies |
lvalue | 1 allocation | 1 allocation | 1 allocation + move |
lvalue SSO | 1 copy | 1 copy | 2 copies |
rvalue | 1 allocation | 1 allocation | 2 moves |
rvalue SSO | 1 copy | 1 copy | 2 copies |
std::string
operations that don’t modify the underlying characters.constexpr
.constexpr
string analysis.std::string_view
should probably take a std::string_view
.std::string_view
with functions that only take a const char*
.