MattWallace
MattWallace

Reputation: 1015

Why isn't std::move a keyword in C++?

Obviously, move semantics/r-value references were a much needed addition in C++11. One thing that has always bugged me though, is std::move. The purpose of std::move is to transform an l-value into an r-value. And yet, the compiler is perfectly happy to let you continue using that value as an l-value and you get to find out at runtime that you screwed up.

It seems like there is a missed opportunity to define move (or some other name) as a keyword (similar to *_cast) and actually have the compiler understand that the referenced value can no longer be used as an l-value here. I'm sure there is some implementation work to do this, but is there some fundamental reason why this wasn't done?

Upvotes: 1

Views: 110

Answers (1)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275585

In C++, moved-from objects in are still objects. They can be used. They are usually in a defined state.

There are some optimizations you can do when you are willing to 'rip the guts' out of an object and use it elsewhere. The C++ committee decided these optimizations should be done implicitly and automatically in a few cases; usually where elision was already permitted, but where it wouldn't work for whatever reason.

Then, the ability to explicitly do this was added. Making this operation end the lifetime of its right hand side would complicate the lifetime rules of C++ to an extreme degree; rather than doing that, they noted they could be highly efficient without complicating the lifetime rules of C++ and leaving them exactly as-is.

It turns out there are a handful of flaws in this; to this extent, C++20 may be adding some "move and destroy the source" operations. In particular, a number of move-construction like operations are easier to write as nothrow if you can both move and destroy the source in one fell swoop.

Actually having it change the lifetime of automatic storage variables is not in the cards. Even describing how such a change would work, let alone making sure it doesn't break anything horribly, would be a challenge.

A simple example of why having it always happen wouldn't be good might be:

Foo foo;
if (some_condition) {
  bar = std::move(foo);
}

the lifetime of foo is now a function of some_condition? You'd either have to ban the above with that kind of construct, or go down a pit of madness you may never get out of.

Upvotes: 2

Related Questions