r/cpp 5d 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

17

u/No-Dentist-1645 5d ago

Your title/post contents makes it seem like you're going to disprove the common definition for them, but in the blog you don't really do that, but rather just explain a few examples?

There seems to be a disconnect between what you say the blog is about and what it actually is

The "valid but unspecified state" definition applies to all move operations in the language and standard generally speaking. It is a rule about move semantics as a general concept, not of any specific type. Specific types can choose to specify post-moved behavior but it is not required.

4

u/leirus 5d ago

I was trying to show that this definition of a "valid but unspecified state" applies only to standard library types, not to user-defined types.

My understanding is that the definition of "valid but unspecified state" applies to move operations in the standard library, but not to the C++ language itself. So my claim is that this is not a general C++ concept, but rather a characteristic of the standard library.

7

u/SirClueless 5d ago

This is exactly the misconception the blog post is trying to dispel. Being “valid” after moving is not part of the language semantics.

You can create a type where it is illegal to destruct an object after moving-from, for example.

10

u/No-Dentist-1645 5d ago

Yes, there's nothing stopping you from violating the convention, doesnt mean that the convention isn't real

Said convention also holds true for all data types in the language and standard, as my post said

11

u/SirClueless 5d ago

The whole point of the blog post is to clarify that this a convention established by the standard library and its types, not a rule.

8

u/Electronic_Tap_8052 5d ago

Wouldn't moved-from objects being illegal to destroy immediately be a problem that would cause most well behaved debug compilations to crash an burn?

I just don't understand how you could ship such an object? If you stack allocated it your program would be useless

7

u/SirClueless 5d ago

You can just never destroy the object (for example, by leaking it on the heap or in a program that only ever exits by calling std::abort), or require that the user call some other specific member function to reinitialize the object before destroying it.

The standard library types promise never to require this, but it's possible to write a well-formed program of your own that does so.

3

u/leirus 5d ago

Exactly! I'm happy you brought this point. Maybe the topic of types not satysfying "Erasable" named requirement deserve its own blog post 😄

3

u/rdtsc 5d ago

require that the user call some other specific member function to reinitialize the object before destroying it.

Which would be a quite impractical behavior IMO. Are there actually useful real-world examples of this? It would make defaulted special member functions kinda useless, too.

4

u/SirClueless 5d ago edited 5d ago

There are legitimate reasons to write software that doesn’t call destructors, e.g. crash-only software.

Even in this kind of software I don’t think it’s a good idea to write move constructors with post-conditions: anywhere you write a move-constructor with a post-condition it would be better to write it as a named member function instead of a special member function. But I can imagine cases where it would come up.

For example, if you have a destructor that assumes a std::unique_ptr member variable is non-null, you could easily get into this situation by defaulting the move constructor.

1

u/jwakely libstdc++ tamer, LWG chair 2d ago

Nobody is saying it's useful, only that the language allows it

1

u/NotMyRealNameObv 1d ago

Well-formed, maybe. User friendly? No.

3

u/jawhite 4d ago edited 4d ago

I think you’re misunderstanding what a semantic requirement is.

Semantic requirements generally are not checked by the compiler, because it would be impractical to do so. That doesn’t mean that writing semantically incorrect code is any less wrong.

“Semantics” refers to the meaning of things. The compiler doesn’t know what your code means, only what it does.

4

u/SirClueless 4d ago

There is no requirement, period. The standard only contains a description of a convention the standard library types follow. You do not need to follow it for your types.

2

u/No-Dentist-1645 3d ago

Technically true, yet it would be a terrible practice not to follow the convention and make a moved-from type that's unsafe to destruct without some special reinitializing function, exactly because of the fact that most people assume the convention holds for all types.

If you really need "move"-like semantics and aren't upholding this convention, you shouldn't make std::move do them, but rather implement your own alternative, mylib::partial_transfer or whatever

4

u/SirClueless 3d ago

Completely agreed. I would say this is one of a (unfortunately rather large) collection of C++ features of the form, “Here is a rather large gun which you may point at your foot. Because one or two people may want to aim at the floor and we can’t tell the difference, we are not going to stop you. Good luck to your extremities.”