Assume we have a simple getter method in a class that returns a const
reference to a std::string
member:
const std::string& getString() const noexcept { return someString; }
With the advent of std::string_view
in C++17, I wonder whether it has any advantages of writing this instead:
const std::string_view getString() const noexcept { return someString; }
Does one method have advantages/disadvantages over the other? Clearly (correct me if I'm wrong) both solutions will definitely be better than this:
const char* getString() const noexcept { return someString.c_str(); }
I've seen this related question, but I'm asking for something slightly different.
Best Answer
Yes, you should write:
Instead of (note: not
const
, because never returnconst
values):The reason is - you already have a
string
. So it's not like you have to pay anything extra to get astring
out of it. Andstring
has one notable semantic difference to an arbitrarystring_view
: it's null-terminated by guarantee. We know this. Maybe some downstream user needs to rely on that information. If they need null-termination (e.g. they need to pass to some C API that requires it) and you give astring_view
, they have to make astring
out of it themselves. You save nothing, but potentially make downstream users do more work.If, however, you had a
vector<char>
instead... then I would suggest to return aspan<char const>
or the equivalent thereof. Since there is no semantic difference and you're just providing a view.There also the separate argument of what:
should do. This either takes a copy of the
string
(expensive, but safe) or effectively a reference to it (cheap, but potentially dangling). But it doesn't entirely look like a reference, it looks like a value. This is a broad issue with reference-semantic types in general (things likereference_wrapper
,string_view
,span
,tuple<T&...>
,optional<T&>
if it existed, etc.).I don't have an answer for this case, but it's something to be aware of.