Look at this example (taken from here):
class foo {
std::string my_str_;
public:
std::string_view get_str() const {
return my_str_.substr(1u);
}
};
This code is bad, because substr
returns a temporary std::string
, so the returned std::string_view
refers to an already-destroyed object. But, if substr
returned std::string_view
, this problem would not exist.
Besides, it seems logical to me if substr
returned std::string_view
instead of std::string
, because the returned string is a view of the string, and it is more performant, because no copy is made.
Would there be any drawbacks if substr
returned std::string_view
(besides the obvious drawback: losing some compatibility with C++14 - I'm not underrating the importance of this, I'd just like know whether other drawbacks exists)?
Related question: How to efficiently get a `string_view` for a substring of `std::string`
The string_view family of template specializations provides an efficient way to pass a read-only, exception-safe, non-owning handle to the character data of any string-like objects with the first element of the sequence at position zero.
The std::string_view, from the C++17 standard, is a read-only non-owning reference to a char sequence. The motivation behind std::string_view is that it is quite common for functions to require a read-only reference to an std::string-like object where the exact type of the object does not matter.
Guideline. It is completely safe to use std::string_view in function parameters if the function needs a non-owning view of a string and doesn't need to store that view somewhere else. Be careful when using std::string_view in return values. Ensure that the function doesn't return a temporary.
std::string is the string class from the standard C++ library. String is some other string class from some other library. It's hard to say from which library, because there are many different libraries that have their own class called String.
When string_view
was invented, there was too much debate on whether it should be there. All the opposing arguments were flowing from examples like the one you showed.
However, like I always tell everyone with such bad examples: C++ is not Java, and is not Python. C++ is a low-level language, where you have almost full control over memory, and I repeat the cliché from Spiderman: With great power comes great responsibility. If you don't know what string_view
is, then don't use it!
The other part of your question has a simple answer, and you answered it yourself:
Would there be any drawbacks if substr returned std::string_view (besides the obvious drawback: losing some compatibility with C++14)?
The harm is that every program that used a copy of the string from substr
may not be valid anymore. Backward compatibility is a serious thing in the computer business, which is why Intel's 64-bit processors still accept x86 instructions, which is also why they're not out of business. It costs a lot of money to reinvent the wheel, and money is a major part in programming. So, unless you're planning to throw all C++ in the garbage and start over (like RUST did), you should maintain the old rules in every new version.
You can deprecate stuff, but very carefully and very slowly. But deprecation isn't like changing the API, which is what you're suggesting.
Here is a concrete (if slightly incomplete) example of code that is currently safe, but would become undefined behaviour with the change:
std::string some_fn();
auto my_substr = some_fn().substr(3, 4);
// ... make use of my_substr ...
Arguably the use of auto
is a little dubious here, but it is completely reasonable (in my opinion) in the following situation, where repeating the type name would be almost redundant:
const char* some_fn();
auto my_substr = std::string(some_fn()).substr(3, 4);
// ... make use of my_substr ...
Edit: Even if substr()
had always returned a std::string_view
, you can imagine this code causing some pain, even if only during development/debugging.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With