Why does moving std::optional not reset state

前端 未结 4 901
野趣味
野趣味 2020-12-31 00:23

I was rather surprised to learn that the move constructor (and assignment for that matter) of std::optional does not reset the optional moved from, as can be se

4条回答
  •  一整个雨季
    2020-12-31 01:18

    Unless otherwise specified, a moved-from object of class type is left in a valid but unspecified state. Not necessarily a "reset state", and definitely not "invalidated".

    For primitive types , moving is the same as copying, i.e. the source is unchanged.

    The defaulted move-constructor for a class type with primitive members will move each member, i.e. leave the primitive members unchanged; a user-defined move constructor might or might not "reset" them.

    A moved-from vector may or may not still have elements in it. We would expect it not to, since that's efficient, but it cannot be relied on.

    A moved-from std::string may still have elements in it, because of Small String Optimization.


    move on std::optional is actually specified by the standard (C++17 [optional.ctor]/7). It is defined as doing move on the contained type, if present. It does not turn a valued optional into a valueless optional.

    So it is actually expected that your code outputs true true, and the actual contained value in foo should stay the same too.


    Regarding the question of why std::optional 's move-constructor is defined this way: I can't say for sure; but an optional is not like a vector with max size of 1. It's more like a variable with a validity flag tacked on. Accordingly, it makes sense for moving an optional to be like moving the variable.

    If moving an optional left the old one "empty", then a = std::move(b); would invoke the destructor of b's managed object, which would be unexpected (to me, at least).

提交回复
热议问题