Earlier quoted context omitted.
> Can you show an example of what you mean? void foo(std::unique_ptr && p) { std::random_device rdev {}; auto dist = std::uniform_int_distribution (0, 1); if (dist(rdev)) { auto pp = std::move(p); } }
This is exactly what I meant as irrelevant. If I call `foo(std::move(my_unique_ptr))`, I know for sure, statically, that my_unique_ptr was moved from, as part of the function call process, and I can no longer access it. Whether `foo` chooses to further move from it is irrelevant.
C++ std::move doesn't move anything: A deep dive into Value Categories
41–50 of 220 posts
Re: C++ std::move doesn't move anything: A deep dive into Value Categories
#42Earlier 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.
It is absolutely knowable statically if ownership will be taken. It's not necessarily very easy to do so, but the decision is 100% up to the compiler, as part of overload resolution and optimization choices (like the NRVO analysis that the article mentions). Since ownership is an inherently static concept, it doesn't even make sense to think about "runtime ownership".
Re: C++ std::move doesn't move anything: A deep dive into Value Categories
#43Earlier quoted context omitted.
This is exactly what I meant as irrelevant. If I call `foo(std::move(my_unique_ptr))`, I know for sure, statically, that my_unique_ptr was moved from, as part of the function call process, and I can no longer access it. Whether `foo` chooses to further move from it is irrelevant.
The only thing that is statically known here is that you’re wrong. The function I posted only moves its parameter half the time, at random. You may want to treat it as moved-from either way, but factually that’s just not what is happening.
void foo() {
std::random_device rdev {};
auto dist = std::uniform_int_distribution(0, 1);
if (dist(rdev)) {
int res = 1 + 2;
}
}
I can tell you for sure that the result of 1 + 2 will be 3.Re: C++ std::move doesn't move anything: A deep dive into Value Categories
#44Re: C++ std::move doesn't move anything: A deep dive into Value Categories
#45Re: C++ std::move doesn't move anything: A deep dive into Value Categories
#46> 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(…
Re: C++ std::move doesn't move anything: A deep dive into Value Categories
#47So the fault here is with std::vector who didn't write that contract.
Re: C++ std::move doesn't move anything: A deep dive into Value Categories
#48> 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…
> So, what are the forces that have determined the current state of C++? A subset of the language aimed at library writers. As a user of those libraries all these weirdo features are likely to be transparent.
Re: C++ std::move doesn't move anything: A deep dive into Value Categories
#49Earlier quoted context omitted.
> So, what are the forces that have determined the current state of C++? A subset of the language aimed at library writers. As a user of those libraries all these weirdo features are likely to be transparent.
TFA explains how std::move is tricky to use and this is not a feature reserved for library writers
Re: C++ std::move doesn't move anything: A deep dive into Value Categories
#50> 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(…
Since you can also put noexcept(false) to indicate something throws exceptions and you didn't just forget to mark it noexcept, it's not a bad policy to say every move constructor should have a noexcept marker.