There're plenty of articles discussing value semantics vs reference semantics, and maybe more trying to explain move semantics. However, No one has ever talked about the connection between value semantics and move semantics. Are they orthogonal concepts?
Note: This question is NOT about comparing value semantics vs move semantics, cause it is perfectly clear these two concepts are not "comparable". This question is about how they are connected, specifically (like #StoryTeller said), about discussing(how):
Move semantics help facilitate more use of value types.
From the original move proposal:
Copy vs Move
C and C++ are built on copy semantics. This is a Good Thing. Move
semantics is not an attempt to supplant copy semantics, nor undermine
it in any way. Rather this proposal seeks to augment copy semantics. A
general user defined class might be both copyable and movable, one or
the other, or neither.
The difference between a copy and a move is that a copy leaves the
source unchanged. A move on the other hand leaves the source in a
state defined differently for each type. The state of the source may
be unchanged, or it may be radically different. The only requirement
is that the object remain in a self consistent state (all internal
invariants are still intact). From a client code point of view,
choosing move instead of copy means that you don't care what happens
to the state of the source.
For PODs, move and copy are identical operations (right down to the
machine instruction level).
I guess one could add to this and say:
Move semantics allows us to keep value semantics, but at the same time gain the performance of reference semantics in those cases where the value of the original (copied-from) object is unimportant to program logic.
Inspired by Howard's answer, I wrote an article about this topic, hope it can help someone that's also wondering about it. I copy/paste the article here.
While I was learning move semantics, I always had a feeling, that even though I knew the concept quite well, I cannot fit it into the big picture of C++. Move semantics is not like some syntactic sugar that solely exists for convenience, it deeply affected the way people think and write C++ and has become one of the most important C++ idioms. But hey, the pond of C++ was already full of other idioms, when you throw move semantics in, mutual extrusion comes with it. Did move semantics break, enhance or replace other idioms? I don't know, but I want to find out.
Value Semantics
Value semantics is what makes me start to think about this problem. Since there aren't many things in C++ with the name "semantics", I naturally thought, "maybe value and move semantics have some connections?". Turns out, it's not just connections, it's the origin:
Move semantics is not an attempt to supplant copy semantics, nor undermine it in any way. Rather this proposal seeks to augment copy semantics.
- Move Semantics Proposal, September 10, 2002
Perhaps you've noticed it uses the wording "copy semantics", in fact, "value semantics" and "copy semantics" are the same thing, and I'll use them interchangeably.
OK, so what is value semantics? isocpp has a whole page talking about it, but basically, value semantics means assignment copies the value, like T b = a;. That's the definition, but often times value semantics just means to create, use, store the object itself, pass, return by value, rather than pointers or references.
The opposite concept is reference semantics, where assignment copies the pointer. In reference semantics, what's important is identity, for example T& b = a; , we have to remember that b is an alias of a, not anything else. But in value semantics, we don't care about identity at all, we only care about the value an object1 holds. This is brought by the nature of copy, because a copy is ensured to give us two independent objects that hold the same value, you can't tell which one is the source, nor does it affect usage.
Unlike other languages(Java, C#, JavaScript), C++ is built on value semantics. By default, assignment does bit-wise-copy(if no user-defined copy ctor is involved), arguments and return values are copy-constructed(yes I know there's RVO). Keeping value semantics is considered a good thing in C++. On the one hand, it's safer, because you don't need to worry about dangling pointers and all the creepy stuff; on the other hand, it's faster, because you have less indirection, see here for the official explanation.
Move Semantics: V8 Engine on the Value Semantics Car
Move semantics is not an attempt to supplant copy semantics. They are totally compatible with each other. I came up with this metaphor which I feel describes their relation really well.
Imagine you have a car, it ran smoothly with the built-in engine. One day, you installed an extra V8 engine onto this car. Whenever you have enough fuel, the V8 engine is able to speed up your car, and that makes you happy.
So, the car is value semantics, and the V8 engine is move semantics. Installing an engine on your car does not require a new car, it's still the same car, just like using move semantics won't make you drop value semantics, because you're still operating on the object itself not its references or pointers. Further more, the move if you can, else copy strategy, implemented by the binding preferences, is exactly like way engine is chosen, that is to use V8 if you can(enough fuel), otherwise fall back to the original engine.
Now we have a pretty good understanding of Howard Hinnant(main author of the move proposal)'s answer on SO:
Move semantics allows us to keep value semantics, but at the same time gain the performance of reference semantics in those cases where the value of the original (copied-from) object is unimportant to program logic.
EDIT: Howard added some comment that really worth mentioning. By definition, move semantics acts more like reference semantics, because the moved-to and moved-from objects are not independent, when modifying(either by move-construction or move-assignment) the moved-to object, the moved-from object is also modified. However, it doesn't really matter——when move semantics takes place, you don't care about the moved-from object, it's either a pure rvalue (so nobody else has a reference to the original), or when the programmer specifically says "I don't care about the value of the original after the copy" (by using std::move instead of copy). Since modification to the original object has no impact on the program, you can use the moved-to object as if it's an independent copy, retaining the appearance of value semantics.
Move Semantics and Performance Optimization
Move semantics is mostly about performance optimization: the ability to move an expensive object from one address in memory to another, while pilfering resources of the source in order to construct the target with minimum expense.
- Move Semantics Proposal
As stated in the proposal, the main benefit people get from move semantics are performance boost. I'll give two examples here.
The optimization you can see
Suppose we have a handler(whatever that is) which is expensive to construct, and we want to store it into a map for future use.
std::unordered_map<string, Handler> handlers;
void RegisterHandler(const string& name, Handler handler) {
handlers[name] = std::move(handler);
}
RegisterHandler("handler-A", build_handler());
This is a typical use of move, and of course it assumes Handler has a move ctor. By moving(not copying)-constructing a map value, a lot of time may be saved.
The optimization you can't see
Howard Hinnant once mentioned in his talk that, the idea of move semantics came from optimizing std::vector. How?
A std::vector<T> object is basically a set of pointers to an internal data buffer on heap, like begin() and end(). Copying a vector is expensive due to allocating new memory for the data buffer. When move is used instead of copy, only the pointers get copied and point to the old buffer.
What's more, move also boosts vector insert operation. This is explained in the vector Example section in the proposal. Say we have a std::vector<string> with two elements "AAAAA" and "BBBBB", now we want to insert "CCCCC" at index 1. Assuming the vector has enough capacity, the following graph demonstrates the process of inserting with copy vs move.
(source: qnssl.com)
Everything shown on the graph is on heap, including the vector's data buffer and each element string's data buffer. With copy, str_b's data buffer has to be copied, which involves a buffer allocation then deallocation. With move, old str_b's data buffer is reused by the new str_b in the new address, no buffer allocation or deallocation is needed(As Howard pointed out, the "data" that old str_b now points to is unspecified). This brings a huge performance boost, yet it means more than that, because now you can store expensive objects into a vector without sacrificing performance, while previously having to store pointers. This also helps extend usage of value semantics.
Move Semantics and Resource Management
In the famous article Rule of Zero, the author wrote:
Using value semantics is essential for RAII, because references don’t affect the lifetime of their referrents.
I found it to be a good starting point to discuss the correlation between move semantics and resource management.
As you may or may not know, RAII has another name called Scope-Bound Resource Management (SBRM), after the basic use case where the lifetime of an RAII object ends due to scope exit. Remember one advantage of using value semantics? Safety. We know exactly when an object's lifetime starts and ends, just by looking at its storage duration, and 99% of the time we'll find it at block scope, which makes it very simple. Things get a lot more complicated for pointers and references, now we have to worry about whether the object that is referenced or pointed to has been released. This is hard, what makes it worse is that these objects usually exist in different scope from its pointers and references.
It's obvious why value semantics gets along well with RAII —— RAII binds the life cycle of a resource to the lifetime of an object, and with value semantics, you have a clear idea of an object's lifetime.
But, resource is about identity…
Though value semantics and RAII seems to be a perfect match, in reality it was not. Why? Fundamentally speaking, because resource is about identity, while value semantics only cares about value. You have an open socket, you use the very socket; you have an open file, you use the very file. In the context of resource management, there aren't things with the same value. A resource represents itself, with unique identity.
See the contradiction here? Prior to C++11, if we stick with value semantics, it was hard to work with resources cause they cannot be copied, therefore programmers came up with some workarounds:
Use raw pointers;
Write their own movable-but-not-copyable class(often Involves private copy ctor and operations like swap and splice);
Use auto_ptr.
These solutions intended to solve the problem of unique ownership and ownership transferring, but they all have some drawbacks. I won't talk about it here cause it's everywhere on the Internet. What I would like to address is that, even without move semantics, resource ownership management can be done, it's just that it takes more code and is often error-prone.
What is lacking is uniform syntax and semantics to enable generic code to move arbitrary objects (just as generic code today can copy arbitrary objects).
- Move Semantics Proposal
Compared to the above statement from proposal, I like this answer more:
In addition to the obvious efficiency benefit, this also affords a programmer a standards-compliant way to have objects that are movable but not copyable. Objects that are movable and not copyable convey a very clear boundary of resource ownership via standard language semantics …my point is that move semantics is now a standard way to concisely express (among other things) movable-but-not-copyable objects.
The above quote has done a pretty good job explaining what move semantics means to resource ownership management in C++. Resource should naturally be movable(by "movable" I mean transferrable) but not copyable, now with the help of move semantics(well actually a whole lot of change at language level to support it), there's a standard way to do this right and efficiently.
The Rebirth of Value Semantics
Finally, we are able to talk about the other aspect(besides performance) of augmentation that move semantics brought to value semantics.
Stepping through the above discussion, we've seen why value semantics fits the RAII model, but at the same time not compatible with resource management. With the arise of move semantics, the necessary materials to fill this gap is finally prepared. So here we have, smart pointers!
Needless to say the importance of std::unique_ptr and std::shared_ptr, here I'd like to emphasize three things:
They follow RAII;
They take huge advantage of move semantics(especially for unique_ptr);
They help keep value semantics.
For the third point, if you've read Rule of Zero, you know what I'm talking about. No need to use raw pointers to manage resources, EVER, just use unique_ptr directly or store as member variable, and you're done. When transferring resource ownership, the implicitly constructed move ctor is able to do the job well. Better yet, the current specification ensures that, a named value in the return statement in the worst case(i.e. without elisions) is treated as an rvalue. It means, returning by value should be the default choice for unique_ptr.
std::unique_ptr<ExpensiveResource> foo() {
auto data = std::make_unique<ExpensiveResource>();
return data;
}
std::unique_ptr<ExpensiveResource> p = foo(); // a move at worst
See here for a more detailed explanation. In fact, when using unique_ptr as function parameters, passing by value is still the best choice. I'll probably write an article about it, if time is available.
Besides smart pointers, std::string and std::vector are also RAII wrappers, and the resource they manage is heap memory. For these classes, return by value is still preferred. I'm not too sure about other things like std::thread or std::lock_guard cause I haven't got chance to use them.
To summarize, by utilizing smart pointers, value semantics now truly gains compatibility with RAII. At its core, this is powered by move semantics.
Summary
So far we've gone through a lot of concepts and you probably feel overwhelmed, but the points I want to convey are simple:
Move semantics boosts performance while keeping value semantics;
Move semantics helps bring every piece of resource management together to become what it is today. In particular, it is the key that makes value semantics and RAII truly work together, as it should have been long ago.
I'm a learner on this topic myself, so feel free to point out anything that you feel is wrong, I really appreciate it.
[1]: Here object means "a piece of memory that has an address, a type, and is capable of storing values", from Andrzej's C++ blog.
Related
I'm a little bit confused about the main use of std::unique/shared_ptr(std::vector<>) when I can simply use a std::vector<>, which, as I know, is itself inherently a dynamic array. As I have also seen around, people say that there is no any performance difference between these two. So, based on all this, what is the point of using a smart pointer pointing to a container (in this case, a vector) instead of a vector alone?
First of all, you shouldn't be using std::shared_ptr unless you need the specific "shared ownership" semantics associated with std::shared_ptr. If you need a smart pointer, you should default to std::unique_ptr by default, and only switch away from it in the scenario where you expressly find that you need to.
Secondly: ostensibly, the reason to prefer std::unique_ptr<TYPE> over TYPE is if you plan to move the object around a lot. This is the common design paradigm for large objects that are either unmovable, or otherwise expensive to move—i.e. they implemented a Copy Constructor and didn't implement a Move Constructor, so moves are forced to behave like a Copy.
std::vector, however, does have relatively efficient move semantics: if you move a std::vector around, regardless of how complex its contained types are, the move only constitutes a couple of pointer swaps. There's no real risk that moving a std::vector will incur a large amount of computational complexity. Even in the scenario where you're overriding a previously allocated array (invoking the Destructors of all objects in the vector), you'd still have that complexity if you were using std::unique_ptr<std::vector<TYPE>> instead, saving you nothing.
There are two advantages to std::unique_ptr<std::vector<TYPE>>. The first of which is that it gets rid of the implicit copy constructor; maybe you want to enforce to maintaining programmers that the object shouldn't be copied. But that's a pretty niche use. The other advantage is that it allows you to stipulate the scenario where there's no vector, i.e. vec.size() == 0 is a different condition than doesNotExist(vec). But even in that scenario, you should be preferring std::optional<std::vector> instead, which better conveys through the code the intent of the object. Granted, std::optional is only available in C++17→ Code, so maybe you're in an environment that hasn't implemented it yet. But otherwise, there's little reason to use std::unique_ptr<std::vector>.
So in general, I don't believe there are practical uses for std::unique_ptr<std::vector>. There's no practical performance difference between it and std::vector, and using it will just make your code needlessly complex.
I'm trying to more fully understand when to implement move semantics, and I believe it's intertwined with what the benefits are.
So far I'm aware of two.
Saving two likely expensive operations when moving an object (copying when the source is known to vanish soon and not be used), without move a a full copy and a full destructor would have been executed, move will save an atomic increment and decrement for atomically reference counted objects, the deep copy of bitmaps or other data structures held by pointers, or a duplication of a file handle, one of which would be closed, or any other pair of "copy" and "destruct"
Implement objects that can't be copied (as in duplicated), but can be moved, making sure there's ever only a single object with the same contents, yet the object can be handed off to a function. E.g. unique_ptr, or any object where copying is not possible or desired, but it needs to be created in one place but used somewhere else.
The distinction between the two is that the first deals with performance and the second with preventing semantic copying.
My question is this, are there any other uses or advantages to implementing move semantics for a class? A consideration other than performance or making sure only one location contains a live copy of the object.
When you move a container in certain contexts, the pointers and references and iterators travel with it. When you copy it, they do not. This is neither performance, nor an unmovable object; rather, move offers a different set of guarantees than copy.
This also can hold whenever you can have anything reference-like that talks about the "inside" of a complex object. move logically can make that reference travel, while copy may not.
It is related to your points, but I think another benefit of move semantics is as a way of documenting ownership in your code. By using move you can make it clear that ownership of an object has been transferred from one place to another. This makes it easier to reason about code.
If you are trying to debug a program and understand the lifetime of an object, it is easier if there is just one path to follow. If ownership transfer is implemented as a copy you have to make sure that the lifetime of the original copy of the object has ended as well.
According to the Google style guidelines, "Few classes need to be copyable. Most should have neither a copy constructor nor an assignment operator."
They recommend you make a class uncopyable (that is, not giving it a copy constructor or assignment operator), and instead recommending passing by reference or pointer in most situations, or using clone() methods which cannot be invoked implicitly.
However, I've heard some arguments against this:
Accessing a reference is (usually) slower than accessing a value.
In some computations, I might want to leave the original object the way it is and just return the changed object.
I might want to store the value of a computation as a local object in a function and return it, which I couldn't do if I returned it by reference.
If a class is small enough, passing by reference is slower.
What are the positives/negatives of following this guideline? Is there any standard "rule of thumb" for making classes uncopyable? What should I consider when creating new classes?
I have two issues with their advice:
It doesn't apply to modern C++, ignoring move constructors/assignment operators, and so assumes that taking objects by value (which would have copied before) is often inefficient.
It doesn't trust the programmer to do the right thing and design their code appropriately. Instead it limits the programmer until they're forced to break the rule.
Whether your class should be copyable, moveable, both or neither should be a design decision based on the uses of the class itself. For example, a std::unique_ptr is a great example of a class that should only be moveable because copying it would invalidate its entire purpose. When you design a class, ask yourself if it makes sense to copy it. Most of the time the answer will be yes.
The advice seems to be based on the belief that programmers default to passing objects around by value which can be expensive when the objects are complex enough. This is just not true any more. You should default to passing objects around by value when you need a copy of the object, and there's no reason to be scared of this - in many cases, the move constructor will be used instead, which is almost always a constant time operation.
Again, the choice of how you should pass objects around is a design decision that should be influenced by a number of factors, such as:
Am I going to need a copy of this object?
Do I need to modify this object?
What is the lifetime of the object?
Is the object optional?
These questions should be asked with every type you write (parameter, return value, variable, whatever). You should find plenty of uses for passing objects by value that don't lead to poor performance due to copying.
If you follow good C++ programming practices, your copy constructors will be bug free, so that shouldn't be a concern. In fact, many classes can get away with just the defaulted copy/move constructors. If a class owns dynamically allocated resources and you use smart pointers appropriately, implementing the copy constructor is often as simple as copying the objects from the pointers - not much room for bugs.
Of course, this advice from Google is for people working on their code to ensure consistency throughout their codebase. That's fine. I don't recommend blindly adopting it in its entirety for a modern C++ project, however.
I am basically trying to figure out, is the whole "move semantics" concept something brand new, or it is just making existing code simpler to implement? I am always interested in reducing the number of times I call copy/constructors but I usually pass objects through using reference (and possibly const) and ensure I always use initialiser lists. With this in mind (and having looked at the whole ugly && syntax) I wonder if it is worth adopting these principles or simply coding as I already do? Is anything new being done here, or is it just "easier" syntactic sugar for what I already do?
TL;DR
This is definitely something new and it goes well beyond just being a way to avoid copying memory.
Long Answer: Why it's new and some perhaps non-obvious implications
Move semantics are just what the name implies--that is, a way to explicitly declare instructions for moving objects rather than copying. In addition to the obvious efficiency benefit, this also affords a programmer a standards-compliant way to have objects that are movable but not copyable. Objects that are movable and not copyable convey a very clear boundary of resource ownership via standard language semantics. This was possible in the past, but there was no standard/unified (or STL-compatible) way to do this.
This is a big deal because having a standard and unified semantic benefits both programmers and compilers. Programmers don't have to spend time potentially introducing bugs into a move routine that can reliably be generated by compilers (most cases); compilers can now make appropriate optimizations because the standard provides a way to inform the compiler when and where you're doing standard moves.
Move semantics is particularly interesting because it very well suits the RAII idiom, which is a long-standing a cornerstone of C++ best practice. RAII encompasses much more than just this example, but my point is that move semantics is now a standard way to concisely express (among other things) movable-but-not-copyable objects.
You don't always have to explicitly define this functionality in order to prevent copying. A compiler feature known as "copy elision" will eliminate quite a lot of unnecessary copies from functions that pass by value.
Criminally-Incomplete Crash Course on RAII (for the uninitiated)
I realize you didn't ask for a code example, but here's a really simple one that might benefit a future reader who might be less familiar with the topic or the relevance of Move Semantics to RAII practices. (If you already understand this, then skip the rest of this answer)
// non-copyable class that manages lifecycle of a resource
// note: non-virtual destructor--probably not an appropriate candidate
// for serving as a base class for objects handled polymorphically.
class res_t {
using handle_t = /* whatever */;
handle_t* handle; // Pointer to owned resource
public:
res_t( const res_t& src ) = delete; // no copy constructor
res_t& operator=( const res_t& src ) = delete; // no copy-assignment
res_t( res_t&& src ) = default; // Move constructor
res_t& operator=( res_t&& src ) = default; // Move-assignment
res_t(); // Default constructor
~res_t(); // Destructor
};
Objects of this class will allocate/provision whatever resource is needed upon construction and then free/release it upon destruction. Since the resource pointed to by the data member can never accidentally be transferred to another object, the rightful owner of a resource is never in doubt. In addition to making your code less prone to abuse or errors (and easily compatible with STL containers), your intentions will be immediately recognized by any programmer familiar with this standard practice.
In the Turing Tar Pit, there is nothing new under the sun. Everything that move semantics does, can be done without move semantics -- it just takes a lot more code, and is a lot more fragile.
What move semantics does is takes a particular common pattern that massively increases efficiency and safety in a number of situations, and embeds it in the language.
It increases efficiency in obvious ways. Moving, be it via swap or move construction, is much faster for many data types than copying. You can create special interfaces to indicate when things can be moved from: but honestly people didn't do that. With move semantics, it becomes relatively easy to do. Compare the cost of moving a std::vector to copying it -- move takes roughly copying 3 pointers, while copying requires a heap allocation, copying every element in the container, and creating 3 pointers.
Even more so, compare reserve on a move-aware std::vector to a copy-only aware one: suppose you have a std::vector of std::vector. In C++03, that was performance suicide if you didn't know the dimensions of every component ahead of time -- in C++11, move semantics makes it as smooth as silk, because it is no longer repeatedly copying the sub-vectors whenever the outer vector resizes.
Move semantics makes every "pImpl pattern" type to have blazing fast performance, while means you can start having complex objects that behave like values instead of having to deal with and manage pointers to them.
On top of these performance gains, and opening up complex-class-as-value, move semantics also open up a whole host of safety measures, and allow doing some things that where not very practical before.
std::unique_ptr is a replacement for std::auto_ptr. They both do roughly the same thing, but std::auto_ptr treated copies as moves. This made std::auto_ptr ridiculously dangerous to use in practice. Meanwhile, std::unique_ptr just works. It represents unique ownership of some resource extremely well, and transfer of ownership can happen easily and smoothly.
You know the problem whereby you take a foo* in an interface, and sometimes it means "this interface is taking ownership of the object" and sometimes it means "this interface just wants to be able to modify this object remotely", and you have to delve into API documentation and sometimes source code to figure out which?
std::unique_ptr actually solves this problem -- interfaces that want to take onwership can now take a std::unique_ptr<foo>, and the transfer of ownership is obvious at both the API level and in the code that calls the interface. std::unique_ptr is an auto_ptr that just works, and has the unsafe portions removed, and replaced with move semantics. And it does all of this with nearly perfect efficiency.
std::unique_ptr is a transferable RAII representation of resource whose value is represented by a pointer.
After you write make_unique<T>(Args&&...), unless you are writing really low level code, it is probably a good idea to never call new directly again. Move semantics basically have made new obsolete.
Other RAII representations are often non-copyable. A port, a print session, an interaction with a physical device -- all of these are resources for whom "copy" doesn't make much sense. Most every one of them can be easily modified to support move semantics, which opens up a whole host of freedom in dealing with these variables.
Move semantics also allows you to put your return values in the return part of a function. The pattern of taking return values by reference (and documenting "this one is out-only, this one is in/out", or failing to do so) can be somewhat replaced by returning your data.
So instead of void fill_vec( std::vector<foo>& ), you have std::vector<foo> get_vec(). This even works with multiple return values -- std::tuple< std::vector<A>, std::set<B>, bool > get_stuff() can be called, and you can load your data into local variables efficiently via std::tie( my_vec, my_set, my_bool ) = get_stuff().
Output parameters can be semantically output-only, with very little overhead (the above, in a worst case, costs 8 pointer and 2 bool copies, regardless of how much data we have in those containers -- and that overhead can be as little as 0 pointer and 0 bool copies with a bit more work), because of move semantics.
There is absolutely something new going on here. Consider unique_ptr which can be moved, but not copied because it uniquely holds ownership of a resource. That ownership can then be transferred by moving it to a new unique_ptr if needed, but copying it would be impossible (as you would then have two references to the owned object).
While many uses of moving may have positive performance implications, the movable-but-not-copyable types are a much bigger functional improvement to the language.
In short, use the new techniques where it indicates the meaning of how your class should be used, or where (significant) performance concerns can be alleviated by movement rather than copy-and-destroy.
No answer is complete without a reference to Thomas Becker's painstakingly exhaustive write up on rvalue references, perfect forwarding, reference collapsing and everything related to that.
see here: http://thbecker.net/articles/rvalue_references/section_01.html
I would say yes because a Move Constructor and Move Assignment operator are now compiler defined for objects that do not define/protect a destructor, copy constructor, or copy assignment.
This means that if you have the following code...
struct intContainer
{
std::vector<int> v;
}
intContainer CreateContainer()
{
intContainer c;
c.v.push_back(3);
return c;
}
The code above would be optimized simply by recompiling with a compiler that supports move semantics. Your container c will have compiler defined move-semantics and thus will call the manually defined move operations for std::vector without any changes to your code.
Since move semantics only apply in the presence of rvalue
references, which are declared by a new token, &&, it seems
very clear that they are something new.
In principle, they are purely an optimizing techique, which
means that:
1. you don't use them until the profiler says it is necessary, and
2. in theory, optimizing is the compiler's job, and move
semantics aren't any more necessary than register.
Concerning 1, we may, in time, end up with an ubiquitous
heuristic as to how to use them: after all, passing an argument
by const reference, rather than by value, is also an
optimization, but the ubiquitous convention is to pass class
types by const reference, and all other types by value.
Concerning 2, compilers just aren't there yet. At least, the
usual ones. The basic principles which could be used to make
move semantics irrelevant are (well?) known, but to date, they
tend to result in unacceptable compile times for real programs.
As a result: if you're writing a low level library, you'll
probably want to consider move semantics from the start.
Otherwise, they're just extra complication, and should be
ignored, until the profiler says otherwise.
I get that C++ 11 has introduced the new move semantics and as consequence data containers are changed to meet the new definitions and specifications of the language, I don't really get how the standard containers benefits from them.
Also I think that I have got what an Rvalue is and how the move semantics act, the problem is i don't see any useful point about this, moving things and changing their labels doesn't sound like a meaningful feature.
I can ask for a good resource about how map, list, vector, ... are changing in the new C++11 ?
The reason RValues and LValues were introduced is it can be much faster to move object data than it is to perform a copy on it. The performance gain is mainly because of internally stored pointers that do not need to be replicated during a move, which would otherwise involve needless malloc calls and memcpys. For instance, std::string contains a pointer to a char array that can be very large. Copying it would involve copying the data in that char array, moving simply involves copying the pointer to that data.
With respect to LValues and RValues, the only things, of which I'm aware, that have changed, is now we have a shiny new constructor to play with, and many of the member functions have been rewritten to take advantage of move semantics.
For instance, std::vector now has a std::vector::vector(std::vector&& move) ctor, and functions like push_back have been changed to also accept RValues.
This should be, for the most part, seemless to you. If you're writing a library, rather than just using one, you need to know this, and URefs too.
You can check out the containers' descriptions at cppreference, which explains the interface of STL. There, you can find what the C++11 standard adds - it is marked with '(since C++11)' tag. If you click on a container type, it will show you which methods are new for it.