Example of the perils of binding rvalues to const ref

Olivier Grant via Digitalmars-d digitalmars-d at puremagic.com
Wed Sep 17 06:12:44 PDT 2014


On Tuesday, 16 September 2014 at 15:30:49 UTC, Andrei
Alexandrescu wrote:
> http://www.slideshare.net/yandex/rust-c
>
> C++ code:
>
> std::string get_url() {
>     return "http://yandex.ru";
> }
>
> string_view get_scheme_from_url(string_view url) {
>     unsigned colon = url.find(':');
>     return url.substr(0, colon);
> }
>
> int main() {
>     auto scheme = get_scheme_from_url(get_url());
>     std::cout << scheme << "\n";
>     return 0;
> }
>
> string_view has an implicit constructor from const string& (see 
> "basic_string_view(const basic_string<charT, traits, 
> Allocator>& str) noexcept;" in 
> https://isocpp.org/files/papers/N3762.html). The function 
> get_url() returns an rvalue, which in turn gets bound to a 
> reference to const and implicitly passed to string_view's 
> constructor. The obtained view refers to a dead string.
>
>
> Andrei

I would say the problem with this code is not so much in this
usage example but in the implementation of string_view. Given
string_view aims to be a non-owning reference to a string, it
should prevent such assignments, which is pretty straights
forward to ensure in C++11. Just delete the corresponding
constructor:

     string_view( std::string && ) = delete;

This example, as stated in subsequent answers to your post, is no
different from returning a const reference to a temporary. In
this example, it just happens to be nicely hidden in the
string_view implementation instead of being explicit:

     std::string const & get_url( )
     { return "foo"; }

This has always been a no-no, and C++11 at least now adds the
possibility to refuse such code via deleted functions.

O.


More information about the Digitalmars-d mailing list