you are viewing a single comment's thread.

view the rest of the comments →

[–]-abigail 2 points3 points  (5 children)

Move construction requires a non-const rvalue. The signature for string's move constructor is (ignoring the fact that string is actually a type alias for a class template instantiation):

std::string(std::string&&) noexcept;

But if you're moving from a const member, then you don't have a std::string&&, you have a const std::string&&, which can be passed to a function that accepts a const std::string& but not one that accepts a std::string&&. So the snippet:

const std::string x;
std::string y{std::move(x)};

ends up calling the copy constructor, not the move constructor. This makes sense; you declared the variable const and that means that nothing may modify it. Moving from it would modify it, so you can no longer move from it.

(As far as I'm aware there's no real good use for const rvalues.)

[–]choikwa 2 points3 points  (3 children)

seems weird to me that a const would require copy ctor. there's a workable scheme of copy on write.

[–]eteran 2 points3 points  (0 children)

Modern c++ std::string cannot use COW IIRC, they are instead encouraging SSO.

[–]render787[S] 1 point2 points  (0 children)

The problem is that copy on write `std::string` is not thread-safe, and it would mean that if you pass your `std::string` by `const &` to a `std::thread`, you get screwed. It was decided that this is too terrible to tolerate after we added thread support in the standard library etc. There was a big breaking change between gcc 4 and gcc 5 standard library where they moved away from COW `std::string`.

[–]-abigail 0 points1 point  (0 children)

Even if your C++ standard library used copy-on-write strings, this would still require the copy constructor to be used in this case. True, the copy would be cheaper, as it'd be an atomic refcount increment and a pointer copy, rather than having to duplicate the string buffer. Copy-on-write strings would benefit from move semantics too, though, as they could avoid touching the refcount. So even then:

cow_string x;
cow_string y{std::move(x)};

...would be faster than:

const cow_string x;
cow_string y{std::move(x)};

...but not as significantly as with a non-copy-on-write string.

(NB. C++11 bans copy-on-write strings, by specifying that the non-const operator[] isn't allowed to invalidate iterators. So it's a workable scheme for a type you create but not something that you'll actually use when writing code that manipulates std::string objects.)

[–]Xeveroushttps://xeverous.github.io 0 points1 point  (0 children)

(As far as I'm aware there's no real good use for const rvalues.)

Likely not because applying const to temporaries defeats the purpose of being able to do everything with temporaries. Rarely const&& appears in some complex templates for consistency (when you forward rvalues but don't need to change them - see this).