Live data from Hacker News

C++ std::move doesn't move anything: A deep dive into Value Categories

0xghost.dev

101–110 of 220 posts

Re: C++ std::move doesn't move anything: A deep dive into Value Categories

#101
post #64
post #60

> [std::move silently copies const values, because] If something is const, you can’t move from it by definition. Whoever wrote that definition should have a thing or two to learn from Rust. Different language I know, but it proves that it wasn't needed to cause so much confussion and collectively so much time and performance lost. Also, who writes rules like that and ends the day satisfied with the result? It seems u…

There was no Rust in 2011.

Rust did exist in some form in 2011. Source: I ate lunch with part of the Rust team in 2011.

Re: C++ std::move doesn't move anything: A deep dive into Value Categories

#104
post #22

> So the standard library plays it safe: if your move constructor might throw (because you didn’t mark it noexcept), containers just copy everything instead. That “optimization” you thought you were getting? It’s not happening. This is a bit of a footgun and clang-tidy has a check for it: performance-noexcept-move-constructor. However, I don't think it's enabled by default!

The reason performance-noexcept-move-constructor is not enabled by default is likely because blindly applying noexcept is dangerous if the underlying logic isn't actually exception-free. If you let clang-tidy slap noexcept on a move constructor that does end up throwing (perhaps because it calls into a legacy member or allocates memory internally), the runtime behavior changes from caught exception to std::terminate(…

The documentations seems to say that option only causes the compiler to issue a warning when move constructors are not marked noexcept - it doesn't override anything.

https://clang.llvm.org/extra/clang-tidy/checks/performance/n... constructor.html

Note that the way std::vector (and other STL containers) require noexcept move constructors for reallocation is by using template matching, and of course any other code might be doing this too, so having a compiler option that forced a constructor (or anything) to have a type signature different than the way it was declared would be a pretty dangerous thing to do since it'd be hard to know what the consequences would be.

Re: C++ std::move doesn't move anything: A deep dive into Value Categories

#105

Earlier quoted context omitted.

What’s the problem? It makes perfect sense to me that a const object cannot be moved from, since it violates the constness. Since constness goes hand in hand with thread safety you really don’t want that violation.

Maybe a compiler error that a const object cannot be “moved”? That would force the programmer to remove the std::move, making it clear that its a copy.

There are cases where you would not want to reject such code, though. For example, if std::move() is called inside a template function where the type in some instantiations resolves to const T, and the intent is indeed for the value to be copied. If move may in some cases cause a compiler error, then you would need to write specializations that don't call it.

Re: C++ std::move doesn't move anything: A deep dive into Value Categories

#106
post #8

Earlier quoted context omitted.

Std move doesn’t move ownership. It simply casts into something that could have its ownership taken. Whether or not that actually happens is impossible to identify statically and the value after ownership is consumed is unspecified - sometimes it’s UB to access the value again, sometimes it’s not.

That's quite inaccurate. It needs to remain destructible, and if the type satisfies things like (move-)assignable/copyable, those still need to work as well. For boxed types, it's likely to set them into some null state, in which case dereferencing them might be ill-formed, but it's a state that is valid for those types anyway.

Well it’s unspecified what empty/size return for collections after a move. Not a dereference, not UB but unspecified as I said. UB pops up in hand written code - I’ve seen it and the language doesn’t provide any protection here.

Thankfully clippy lints do exist here to help if you integrate that tooling

Re: C++ std::move doesn't move anything: A deep dive into Value Categories

#107

[flagged]

The issue TFA is describing isn't really about not understanding move semantics, it's about not having read the documentation for the STL container classes, and not therefore realizing that anything requiring reallocation needs a noexcept move constructor (else will fall back to copy construction).

Note that a move constructor that is NOT declared with noexcept is perfectly valid, and will happily be used most of the time (other than where code, such as the STL, is explicitly looking for a noexcept one).

So, for example:

HeavyObject t;

HeavyObject s(std::move(t));

Will cause t to be moved to s.

Re: C++ std::move doesn't move anything: A deep dive into Value Categories

#108
post #2

I always understood move as moving ownership, so it's not a misnomer. > std::move is like putting a sign on your object “I’m done with this, you can take its stuff.” Which exactly is moving ownership.

Well, no, because CAN take isn't the same as WILL take. Changing something to an rvalue means it'll now match a move constructor, but there is no guarantee a move constructor will be used, even if defined, because you've got classes like std::vector that are picky and are explicitly looking for a noexcept move constructor.

In that sense, std::move() is no different than other passing semantics. Just because you wrote at the call site that you want to pass a copy of your object doesn't mean that the callee will actually make a copy of it.

Re: C++ std::move doesn't move anything: A deep dive into Value Categories

#109

Earlier quoted context omitted.

What’s the problem? It makes perfect sense to me that a const object cannot be moved from, since it violates the constness. Since constness goes hand in hand with thread safety you really don’t want that violation.

Maybe a compiler error that a const object cannot be “moved”? That would force the programmer to remove the std::move, making it clear that its a copy.

clang-tidy has a check for this case

Re: C++ std::move doesn't move anything: A deep dive into Value Categories

#110

Earlier quoted context omitted.

Maybe a compiler error that a const object cannot be “moved”? That would force the programmer to remove the std::move, making it clear that its a copy.

There are cases where you would not want to reject such code, though. For example, if std::move() is called inside a template function where the type in some instantiations resolves to const T, and the intent is indeed for the value to be copied. If move may in some cases cause a compiler error, then you would need to write specializations that don't call it.

I didn’t think of that, but you are right. At some point I thought I understood templates r-value references work but now I’ve forgotten.
Post reply on HN