Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What drawbacks would exist if std::string::substr returned std::string_view?

Tags:

c++

string

c++17

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`

like image 986
geza Avatar asked Sep 04 '17 10:09

geza


People also ask

What is the purpose of string_view?

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.

What is std::string_view?

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.

Is string_view thread safe?

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.

What is the difference between std::string and string?

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.


2 Answers

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.

like image 182
The Quantum Physicist Avatar answered Oct 17 '22 21:10

The Quantum Physicist


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.

like image 35
Arthur Tacca Avatar answered Oct 17 '22 23:10

Arthur Tacca