13

Why is the following snippet legal C++ code? This is a purely theoretical question - there is no usecase that I have in mind:

#include <optional>
#include <vector>
#include <iostream>

int main() {
    std::vector<int> v{1, 2, 3};
    const std::optional<std::vector<int>> ov = v;
    const auto nv = std::move(ov.value());

    for (const auto& x : *ov) { std::cout << x; }
    for (const auto& x : nv) { std::cout << x; }
}

This yields 123123, but I do not understand the reason.

  1. Why is a std::move applied to a value of a const optional legal?
  2. Why does the optional ov still hold the vector?

Does ov.value() internally create a copy to a temporary which is then moved from?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Markus Moll
  • 163
  • 8
  • 10
    Think of std::move() as a cast that does nothing for const objects. Nothing is moved here. – Aedoro May 10 '23 at 10:46
  • 2
    Note that since the move constructor of vector takes an non-const rvalue ref, the construction of nv is done using the _copy_ constructor. – cptFracassa May 10 '23 at 12:19
  • When using `std::move`, I like to follow a policy that the object moved from is in a valid-but-unspecified state (suitable for re-assignment or destruction). In general. In the OP code, since `ov` is `const`, the `std::move` will **not** result in the object being gutted and left behind with an empty husk. Regardless, I find following the idiom that the (potentially) moved-from object is as-if it were an ex-parrot works well. In general. (There are exceptions, such as moving from a `std::unique_ptr` does leave it in a well specified state.) – Eljay May 10 '23 at 12:39
  • `std::vector` is also an exception - a moved-from vector is guaranteed to be empty. – Evg May 10 '23 at 19:18
  • @Evg That's not an exception. empty is a fine example of a valid-but-unspecified state. – Mooing Duck May 16 '23 at 22:42
  • @MooingDuck This makes no sense. Empty is a perfectly specified state. Otherwise, after doing `std::vector::clear()` the resulting vector would have been useless. – Evg May 17 '23 at 01:03
  • @Evg: Moving in general leaves objects in a valid but unspecified state, because moving objects in general can't make specific claims about every possible class you might write. However, almost every class in the C++ standard library does specify a state for that specific class, which is usually but not always the "empty" state. – Mooing Duck May 17 '23 at 15:27
  • For `std::vector` it is always an empty state. – Evg May 17 '23 at 17:45

1 Answers1

18

Why is std::move applied to a value of a const optional legal?

Sure, why not? All that std::move is, is a cast to an rvalue reference. You'll just end up with an rvalue reference to a const object. That's nothing unusual.

Why does the optional ov still holds the vector?

Because it is const, and cannot be changed.

Several conditions must happen in order for an object to be moved. std::move takes care of the most important one, but all others must be satisfied as well.

It is a common misconception that spraying std::move everywhere guarantees a super-duper-efficient move of an object from one place to another, by magic. That's not true, that's not what std::move is, it's just a cast that's sometimes needed in order to move something. But that's not everything that's needed, just the most important part.

user2357112
  • 260,549
  • 28
  • 431
  • 505
Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
  • 8
    This answer is correct, but seems to try hard to avoid saying the obvious thing: `move` is a misnomer, so its users should ignore the name when trying to remember what this function actually does. – Ruslan May 10 '23 at 20:00
  • 1
    I would argue that a "rvalue reference to a const object" is "something unusual", a rvalue reference generally represents an object that is ok to plunder, but a const object cannot be plundered. – plugwash May 10 '23 at 21:15
  • 4
    You emphasise (by repeating twice) that `std::move` is not everything that's needed for a move, but can you name the other things that are needed? A link to a reference would be sufficient. – Bergi May 11 '23 at 00:18