This sounds like an enormous footgun (but as I understand it there are warnings that will tell you). An object isn't "valid" in any reasonable business logic sense just because the fields are initialized to anything at all, such as their default state? If the valid state of a Person is "the name is not empty " and this is enforced by a constructor then I don't want the program to ever have Person object floating around with a blank name? I either want a compiler error (good) or an immediate crash at runtime (bad), but at least I don't want an invalid object in a still running program (worse). Maybe I misunderstand what the reset was or how big this risk is though.
>An object isn't "valid" in any reasonable business logic sense just because the fields are initialized to anything at all, such as their default state
That very much depends on your use case.
>If the valid state of a Person is "the name is not empty " and this is enforced by a constructor then I don't want the program to ever have Person object floating around with a blank name
If you have such strict requirements then you shouldn't be moving around Persons to begin with. You should just be using std::make_unique() and then moving the pointer. Person should not even have a move constructor defined. If you code your class such that it's possible to let it reach an invalid state, that's no one's fault but your own.
Even if the std::string was guaranteed to hold a "SORRY, THIS STRING HAS BEEN MOVED FROM, PLEASE CONTACT YOUR LOCAL STRING SUPPLIER" string in it after being moved from, I doubt this would actually help that much with the overall correctness of the application.
There are very, very few cases where it is "sensible" to do anything with such an "arbitrarily conjured" state except than disposing of/overwriting it. In fact, the only example I can vaguely remember of (and can't for the life of me to google) is that one scheme of storing some sort of lookup index in two arrays that store indices into each other, and it's not necessary to zero out those arrays before using them because the access algorithm is cleverly arranged in such a way that no matter what numbers are stored in the unused parts of the arrays, it will still work correctly.
>Even if the std::string was guaranteed to hold a "SORRY, THIS STRING HAS BEEN MOVED FROM, PLEASE CONTACT YOUR LOCAL STRING SUPPLIER" string in it after being moved from
That's a rather weak "even if", given most implementations just reset to the empty string after moving.
>I doubt this would actually help that much with the overall correctness of the application.
Like I said, it depends on your use case. A pattern I use frequently when processing input is to have an accumulator that I build up progressively, and then when ready I move it into a result container, and since that resets the accumulator I can simply keep using it. If my algorithm required the initial state "SORRY, THIS STRING HAS BEEN MOVED FROM, PLEASE CONTACT YOUR LOCAL STRING SUPPLIER" rather than the empty string, such an idiosyncratic post-move value would be rather convenient.
> If you code your class such that it's possible to let it reach an invalid state, that's no one's fault but your own.
I don't know C++ so I was given the impression in the article that the person writing the class could try very hard to make it impossible to reach an invalid state, but that this work could be ignored elsewhere by making a move of this kind which would work without any special requirements on the type itself.
You can delete the move constructor and the move assignment operator from a class, making it completely impossible to move its objects (other than through pointer arithmetic). If you have really specific class invariants it's what you should be doing. OR, the move functions should leave the moved-from members in valid states according to your invariants.
The lack of so called destructive moves in C++ is not great. You either add a proper empty state to your type and make it properly part of the invariant, which is not always possible or meaningful, or you need a special moved from state for which your object invariant doesn't hold, which is "less than ideal" to say the least.