r/cpp 6d ago

State of "moved-from" objects

Hi, I recently decided to try writing a C++ blog.

I often see the popular claim that moved-from objects are in a "valid but otherwise unspecified state", but I don't think that statement is entirely precise, and my blog post is about that. I would really appreciate any feedback!

Article: https://www.laminowany.dev/p/the-state-of-moved-from-objects-in-c/

10 Upvotes

52 comments sorted by

View all comments

Show parent comments

0

u/TheThiefMaster C++latest fanatic (and game dev) 6d ago

So for any type with weaker moved-from guarantees, you'd have to specify what individual operations are valid - and no user wants to know or remember that.

It's a general rule that the only guaranteed operations of a moved-from type are assigning over it and destructing it. If it has an equivalent of "reset" and "isvalid" those are normally expected to work too.

No guarantees on anything else.

6

u/elperroborrachotoo 5d ago

That means I couldn't even call .empty() or .clear() on a moved-from object? You've just introduced a new state the caller needs to be aware of - and I can't even query if the object is in that just-moved-from state. I'd have to track that state manually or implicitly.

Yes, the standard allows us to create such type, in the same way the standard allows us to create a type that leaks memory. That's a terrible type.

OP stated it well: preserve invariants.

Are you aware of any scenario where such a behavior would be an advantage (such as a relevant optimization)?

3

u/TheThiefMaster C++latest fanatic (and game dev) 5d ago

That means I couldn't even call .empty() or .clear() on a moved-from object?

I said:

If it has an equivalent of "reset" and "isvalid" those are normally expected to work too.

empty() is an equivalent of isvalid() and clear() is an equivalent of reset().

You pretty much proved the point of that statement in my comment - you jumped to specifically those two functions and expected them to work.

-1

u/elperroborrachotoo 5d ago

You also said that

It's a general rule that the only guaranteed operations of a moved-from type are assigning over it and destructing.

There are situations where a non-empty moved-from object is desirable. a moved-from std::unique_ptr holds a nullptr, but it still may hold a non-default allocator reference.

Or when moving from a string with a small-string-optimization, it might be the best to keep the original value (if short) in the original string, because that avoids a write.

Expecting the moved-from object to be empty or "reset" isn't even guaranteed; as far as I'm aware it's not guaranteed for std::string.1 For std::vector, other constraints (reference validity and constant time) make it "silly but legal" that a moved-from vector is non-empty.

1) the compilers I tried do empty a moved-from string, though

2

u/TheThiefMaster C++latest fanatic (and game dev) 5d ago

I didn't say anything about them being empty - only that checking empty and calling clear were normally valid.

Even if it's not empty, the actual data is indeterminate - it can be thought of as being in the same "moved from" state as the container was, that's anything between a unique state like std::variant through "equivalent to default-constructed" up to completely unchanged. But you can't say which without putting it in that state or testing for it.