Live data from Hacker News

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

0xghost.dev

121–130 of 220 posts

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

#121
post #120

You read things like this and, first, you're reminded of Sideshow Bob [1] and it puts Rust concepts in context, namely: 1. Move semantics are to handle ownership. Ownership is a first-class concept in Rust. This is why; 2. C++ smart pointers (eg std::unique_ptr ) are likewise to handle ownership and incur a runtime cost where in Rust they are handled by the compiler with no runtime cost. Yes you can "cheat" (eg std::…

[dead]

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

#122

Before move semantics the HeavyObject problem was solved in most cases by specializing std::swap for each container. The design lesson I draw from this is that pursing a 100% general solution to a real problem is often worse than accepting a crude solution which covers the most important cases.

my take looking at languages beyond C++ is a very different one

you want a well working general solution which works well (most of the time for most of the "generic code" (i.e. good defaults for the default use-case).

and then add escape hatches for micro-optimizations, micro-control etc.

C++ on the other hand was deeply rooted designed with micro optimizations and micro control first.

"Generic solutions" where then tried to be added on top, but not by changing a badly working abstraction/design but by adding more abstraction layers and complexity on top. And with a high requirements for back/forward compatibility, not just with the language but ton of different tooling. That this isn't playing out well is kinda not really surprising IMHO. I mean adding more abstraction layers instead of fixing existing abstraction layers rarely plays out well (1) especially if the things you add are pretty leaky abstractions.

-----

(1): In context of them archiving overall the same goal with just different details and no clear boundaries. Layering very different kind of layers is normal and does make sense in a lot of situations. Just what C++ does is like layering "a generic system programming language" (modern C++) on top of "a generic system programming language" (old C++) without clear boundaries.

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

#123

Regarding mistake 1: return std::move(local_var), it is worth clarifying why this is technically a pessimization beyond just breaking NRVO. It comes down to the change in C++17 regarding prvalues. > Pre-C++17, a prvalue was a temporary object. > Post-C++17, a prvalue is an initializer. It has no identity and occupies no storage until it is materialized.

In C++17 and later, return std::move(local_variable) as opposed to return local_variable is only breaking NRVO (which avoids even having to move, by essentially replacing local_variable with a reference to the variable the caller is assigning the function result to).

In C++17 if you do return std::move(local_variable) it will do exactly what you asked for and move the local variable to the return value, which with copy elision means directly to the caller's variable.

So, return std::move(local_variable) is only preventing NRVO, it's not preventing a move (even though you shouldn't be asking for a move, because move is not the most efficient way).

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

#124
post #32

About 28 years ago, I figured out that I’m just not smart enough to use C++. There are so many foot guns and so much rampant complexity that I can’t keep it all straight. I crave simplicity and it always felt like C++ craved the opposite.

Systems programming in the large is hard, owning the category for decades harder still. Even languages that have tried to fast-follow and disrupt C++ end up looking a lot like C++. There is an irreducible complexity.

What does in the large mean?

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

#125
You should almost never ever be writing your own move constructors. Use compiler generated defaults. It's only for very rare specialist classes that you need to override compiler generated defaults. Many times when you think you need to you often don't.

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

#126
post #74
post #32

About 28 years ago, I figured out that I’m just not smart enough to use C++. There are so many foot guns and so much rampant complexity that I can’t keep it all straight. I crave simplicity and it always felt like C++ craved the opposite.

I understand the individual rationales of C++ things but I lost the faith on the whole thing.

The way C++ has developed over the past 20 years seems similar to someone starting with an algorithm that fails for some edge cases, and patching the behavior with a different hack for each edge case, which breaks other cases, then patching those, and on and on forever.

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

#127

> This code works. It compiles. It runs. But depending on how you’ve implemented your types, it might be performing thousands of expensive copy operations instead of cheap moves without you realizing it. I've spent the last two decades in the .net platform. But for a decade or so before that I was a C++/Unix dev. I remember old style "C with classes" C++ as being fairly small and elegant, and approximately as easy to…

> old style "C with classes" C++ as being fairly small and elegant

it (C++) never really was that

but it was possible to use it "as if it where that" (kinda, e.g. there is code which is valid in C but UB in C++)

I mean there where also times where books which told you that in C everything "is just bits in memory" where popular/believed/beloved, even through that never really was true outside of some very specific cases (all of CPU without caches, only in order execution, single core, a mostly non-optimizing compiler, and other requirements). It was just that the chance to run into issues was much less likely if you go ~20+ years back into the past so you could kinda use it like that (at some risk, especially wrt. forward compatibility).

Today you find ton of material even about obscure features, complications, hidden food guns, etc. so things do look/feel far more overwhelming IMHO.

That modern C++ is a bit like a different language glued on top of old C++ doesn't exactly help either.

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

#128
post #32

About 28 years ago, I figured out that I’m just not smart enough to use C++. There are so many foot guns and so much rampant complexity that I can’t keep it all straight. I crave simplicity and it always felt like C++ craved the opposite.

c++ 03 was a lot easier.

For instance, if you want to avoid unnecessary copy operations when returning a string, just return it in variable that you pass by reference (eg. void doSomething(string& str);) likewise avoid the vector class making unnecessary copies, simply by creating the objects on the heap and use a vector of pointers instead of values. It's a bit more ugly, but it works, and you don't need to read a 24 page blog to understand all the corner cases where it can go wrong. modern c++ is all about syntactic suger.

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

#129
> Let me put this in simpler terms: std::move is like putting a sign on your object “I’m done with this, you can take its stuff.”

and later:

> Specifically, that ‘sign’ (the rvalue reference type) tells the compiler to select the Move Constructor instead of the Copy Constructor.

This is the best conceptual definition of what `std::move` is. I feel that is how every book should explain these concepts in C++ because its not a trivial language to get into for programmers who have worked with differently opiniated languages like python and java.

If you read Effective Modern C++ right Item 23 on this, it takes quite a bit to figure out what its really for.

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

#130
post #90

Earlier quoted context omitted.

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(…

I would argue performance-noexcept-move-constructor should always be on. Move constructors should almost always be noexcept since they typically just move pointers around and don't do allocations normally.

eh, depends. for instance think about a small_vector or small_string
Post reply on HN