For people who are new to C++11/14, I would like to share extra information about the topic: Rvalue reference are references in a form T&&, and they have been appeared in C++11. The goal of introduction them is is to have a candidate for the move. 1. An rvalue can be associated with a non-constant reference to an rvalue. 2. Lvalue cannot be bind to an rvalue reference. Move operation are never perfomed from lvalues. 3. If you have two functions: void f(T&&) and void f(T&) then void f(T&&) takes precedence over void f(T&) if both can be called. C++11 noexcept -- call any destructor, allocate memory 4. Move yourself to yourself. There are two point if views a) usually does not get performed, and this is not normal behavior. b) in some styles and languages people do perform some checks. If it is really neglable overhead - maybe worthwhile. 5. EXPLICIT MOVEMENT REQUEST ( first scary thing ). Care must be taken when writing the move constructor, the fact is even argument has T&& and this is an rvalue-reference, but in the body of the function "T&& x" observed by compiler as lvalue. The most confusing thing about C++11. 6. std::move -- converts an expression to an rvalue. std::move could be called rvalue_cast. 7. Second scary thing. There is a special construction T&& parameter Definition in the template, the rule is valid only for constructions of the form: template void f(T&& argument) {} If arg is Lvalue => the function that is indtantiated is void f (T& arg) If arg is equal to Rvalue => the function that is instantiated is void f (T&& arg) Without template definition construction like void f(T&& arg) - is called by C++ Computer Scientists as true rvalue reference. But template trick has another name. In fact: template void f(T&& argument) {} is called universal reference and name has been suggested by Scott Myers. It links everything rvalue and lvalues.
@arnebovarne77594 жыл бұрын
C ++ should be designed so that the use of Move Semantics should be an internal problem for the compiler. Now we act as human compilers who take on a problem that we should not have.
@VictorYarema2 жыл бұрын
It can't be phrased better than this. Indeed C++ is not a standard but just a mess of raw ideas which are forged together in an insanely ugly manner.
@vesk4000 Жыл бұрын
I definitely agree!
@wagsman99993 жыл бұрын
This is one of the more tricky concepts in c++, this presentation went a long way to clarify things, really appreciate it. From what I have gathered, if we use the STL containers, moves will occur naturally where appropriate.
@EgD9964 жыл бұрын
cleared many of my doubts on std::move
@carlosbentzen3 жыл бұрын
Super nice presentation! To the point and answers all questions that come up on the way.
@CppCon3 жыл бұрын
Much appreciated!
@mcs8778 Жыл бұрын
Definitely one of the best presentations in Back to Basics series
@VictorYarema2 жыл бұрын
I can't remember any other such a good programming language concept explanation as this one. David Olsen is a great teacher. Second to none.
@QWin-ir6yqАй бұрын
@@VictorYarema he reads from a script the entire time.
@noaxin9 ай бұрын
24:07 "but this is slideware" love it!
@konstantinburlachenko28432 жыл бұрын
Thanks for the talk. There something with which not all people working with C++ agree: i) Move operations need not be noexcept, but it's preferable. ii) In c++ 11 standart a=std::move(a) has undefined behavior. if you want safe quard for check that I does not stop you. Bu at least in c++11 it was not a required thing to do. iii) A lot of code is written in c99/c++03. In reality nobody returns huge objects by value, so example is not real by 100%, but with std::move we can now forget about that restrictions from c++03.
@NKernytskyy3 жыл бұрын
Great presentation. Plain explanation!
@CppCon3 жыл бұрын
Glad you liked it!
@german.rodriguez4 жыл бұрын
At 53:44: "A question about self move assignment: what are some cases where you would want to do s = std::move(s)? - You don't want ever do that. That really should not ever happen in well-written code. But again, [...] your program should not crash if a user does that, even though they shouldn't". I can't craft a practical example where that could happen and not be wrong code, but I can imagine that is some code is programmatically moving ownership in a loop (I don't know, reordering a list on unique pointers, for example), then, could it happen that such a self assignment could happen inadvertently? Or am I just imagining a sort of case that could really never happen in non-wrong code?
@TheSulross4 жыл бұрын
An object that is moved from will still be subject to being destructed when it goes out of scope - being left in a valid state after a move operation insures it won't seg fault when its destructor executes. An interesting question not asked - is it considered bad practice to start using an object again when it has been moved from, or should it be regarded as now being an "untouchable"? (If it got, say, default constructed by the move, then one could start doing something with it all over again.)
@darranrowe1743 жыл бұрын
I would honestly say it is bad practice. If you move from an object then it can make it more difficult to reason about that object. One of the big issues with move is that when you move from the object, the language doesn't require any real state of the object beyond the object itself is capable of destruction. This means that unless the object itself guarantees some valid state you are going to have to initialise the object again after you move from it. But it is possible to forget to do that. It tends to be much easier to use a helper inline function or even a lambda to do the work and then return it by value to get the move.
@mehmetdemir-lf2vm2 жыл бұрын
53:00 objects in valid state should mean that those objects can be destructed without an exception or memory leak.
@davithov3 жыл бұрын
When you used delete[] data; (where data had type double* ), how did you know that data points to the array? If it was not pointing to the array, won't we have undefined behavior? What I mentioned is the some of the well known issues related to raw pointers.
@davithov3 жыл бұрын
OK, I have already got familiar with your answer to this question in Q&A part, thanks.
@masheroz3 жыл бұрын
@@davithov what was the answer?
@lerusius4 жыл бұрын
On slide 4 doesn't Named Return Value Optimization happen in build_dictionary, resulting in only one copy being made?
@Scorbutics2 жыл бұрын
I wondered the same thing. I'm pretty sure compilers optimize the return value.
@VictorYarema2 жыл бұрын
Compilers don't always do RVO. Yes, in any simplest trivial example there will be most likely RVO applied. But we can also come up with example without it.
@konstantinburlachenko28432 жыл бұрын
What is perfect forwarding? std::move -- casting the value to rvalue unconditionally. std::forward -- conditional cast that just correctly cast references in function templates. template void setX(T&& n) { x = std::forward(n); } In that context std::forward just do correct thing: If T is a reference (i.e.,T is T&) lvalue will be passed to n. If T a non-reference (i.e.,T is T) rvalue was passed to x. Conceptual implementation of std::forward template T&& std::forward(T&& param) noexcept { return static_cast(param); }
@abdulshabazz8597 Жыл бұрын
Most users of KZbin are visual thinkers; it’s better to show only what Should be performed . The correct compiler flags already optimize for performance and efficient move semantics.
@konstantinburlachenko28432 жыл бұрын
Regarding question why std::move is called so - it is just bad name in my vision, the correct name should be rvalue_cast, but it’s std::move
@konstantinburlachenko28432 жыл бұрын
Another what is really std::move does is the following: std::move -- casting the value to rvalue unconditionally. This is the correct implementation: template typename std::remove_reference::type&& move(T&& obj) noexcept { using Type = typename std::remove_reference::type&&; return static_cast(obj); } If you will decide by yourself to do that in another way please be aware there are some subtle rules with Reference collapsing. So it’s the following: You have a template function template void f(T& param); Now you call it and instantiate function explicitly or implicitly. But there are some certain of rules applied for arguments. Several references collapsed into one: T& & ⇒ T& T&& &⇒ T& T& && ⇒ T& T&& && ⇒ T&& Summary: ⇒ T& ⇒ T& ⇒ T&
@masheroz3 жыл бұрын
How do we know what the compiler will do in a default move constructor/assignment?
@darranrowe1743 жыл бұрын
The standard does define this, but since that isn't fun to read then you can use a site like cppreference to see a description of what it does. What it basically does is go through each base and non static member in declared order and then call the move constructor/assignment for each of these. This is why the defaults can only exist if the base and non static have them.
@VoidloniXaarii Жыл бұрын
Great talk, thanks a lot
@ahahTl4 жыл бұрын
very good presentation. thank you .
@trejohnson76772 жыл бұрын
"std::move doesn't move anything."
@hanyanglee90182 жыл бұрын
I don't know if I understand the && in a proper way. It looks like, r ref is a way to specify that this object can be safely destroyed, so please do anything to it. It brings the concept of object lifecycle. I think a better way to convey the idea is directly from object lifecycle rather than if a token can appear on the left side of an assignment.
@InXLsisDeo2 жыл бұрын
Very good presentation, but I had to stop several times because it's going fast.
@jaybee9054 Жыл бұрын
One day I'll understand Rvalue references. Pretty sure. 🤐
@hyiux3 жыл бұрын
Q: How to turn trivial into complicated? A: C++.
@konstantinburlachenko28432 жыл бұрын
If you use swap to implement move - in my practice you should not do that, there are no benefit in move in that case. So you should implement move operation more cheaper.
@kryptick1ng7 ай бұрын
You are wrong. During move assignment, the lvalue could potentially be pointing to a resource. If you do not utilize the concept of swap, then you more than likely run into a scenario where you calling both destructors during the move assignment. You have to call the destructor (or clean up function) for the lvalue to ensure its not pointing to a resource, and the rvalue will more than likely be going out of scope during the move assignment, so it will call its destructor. By utilizing swap, the lvalue takes the contents of the rvalue, and the rvalue will call its destructor with whatever lvalue was pointing to. At minimum, you reduce an entire function call by swapping.
@devatsdb7 Жыл бұрын
this weird, i learn similar concept in rust,which is automatic, now i know why rust take that approach.
@MrLudacrize3 жыл бұрын
Cpp is a twisted language built on patches over patches. Ugly syntax with even uglier semantics
@hyiux3 жыл бұрын
The wonderful world of C++ where initializing a frickin variable can feel like having to master rocket science. kzbin.info/www/bejne/bXW3nYqGnL1psNU&ab_channel=CppCon