What exactly does it mean to say a C++ object is movable?
Asked Answered
V

2

11

Given the following definitions:

  • object -- a contiguous region of memory holding a value of some type.
  • value -- the bits of an object interpreted according to the objects type.

Section 6.4.1 of the C++ Programming Language book [4th ed], when discussing value categories, states:

Movable: The object may be moved from (i.e., we are allowed to move its value to another location and leave the object in a valid but unspecified state, rather than copying.

Question:

  1. What does "move its value to another location" really mean?
  2. How can a value (a bit interpretation) be moved?
  3. How can bytes of an object be "moved" without a copy? Just doesn't make sense.

Can someone please explain?

Vicentevicepresident answered 15/9, 2020 at 23:48 Comment(12)
Keep in mind that this "contiguous region" may contain pointers to other data stored "outside" the object in question. (cf. string and vector)Goeselt
the value won't be moved to another location but the ownership of the value and of the object will be moved to a new owner.Ed
A ‘move’ is a ‘copy’ that “takes ownership” of any contained resources/lifetimes. This could be, for example, copying a pointer value instead of copying the underlying objects. This is why the donor/source is left in a “valid but unspecified state”.Calabrese
Let me test my understanding. With a "move" there is only one instance after the operation? With a copy, there are two instances (the original and the copy). Is this correct?Mchail
Nope. The ‘move’ does not affect the original object’s lifetime at all. However, as the original is left in a “valid but unspecified state” it is usually invalid to access the original in a meaningful way.Calabrese
@ThomasMatthews depends on what's considered an instance. The moved from object is still an object. Just shouldn't be used until it's set to a valid state.Ninepins
@ThomasMatthews Not really. After a move, there are still two instances, but ownership of all the original object's resources (whatever they might be) has been transferred to the target of the move.Occurrence
Is this like deleting a dynamically allocated object, where the pointer hasn't changed but the deleted object should no longer be used?Mchail
Useful viewing: youtube.com/watch?v=vLinb2fgkHk . You might recognize the presenter's name. He answered the question.Microclimatology
Important note that most commenters are overlooking: There is more to the value of an object than it's contained bits. We can say the value of a std::string is "foobar", but the bits that compose "foobar" aren't actually inside the std::string object. That's very key to understanding move semantics.Coadunate
Given the following definitions Which are not from the Standard.Hardden
@LanguageLawyer stroustrup.com/glossary.htmlVicentevicepresident
U
9
  1. What does "move its value to another location" really mean?

It means that the other location has the value that the original had prior to the move, and that it is not important what value the original location has after the move.

  1. How can a value (a bit interpretation) be moved?

For example, simply by copying. If one wanted to do extra work beyond that (which is not motivated with just a bag of bits), one could set the original location to some other bit pattern, such as all zeroes, and it would still be considered a successful move. The difference here with copying is that a copy should leave the original unchanged.

  1. How can bytes of an object be "moved" without a copy? Just doesn't make sense.

A copy is a valid move.

Sometimes the bits in the original have semantics of owning a resource. If there is only one resource, and you simply copy the bits, now both locations "own" the resource, resulting in duplicate disposing of said resource when both objects go out of scope.

So a move would transfer ownership of the resource to the new location and change the original location to not own a resource. A concrete example of this is an owning pointer: copy the pointer then set the original to nullptr.


A copy might be more expensive than a move (and it might not). But continuing with the owning pointer example: If you make a copy of that object, then after the copy, two resources must exist (assuming unique ownership of the resource).

So a copy doesn't copy the pointer. The copy copies the resource and then the new location points to the new resource. If the creation of that resource is expensive, then a move can be much cheaper by just copying the pointer and nulling the original.


Generally speaking, move should be an optimization of copy when the type supports both operations. move should never be more expensive than copy. And if move has the same expense as copy, then the move operations can simply be not implemented and copy will handle moves seamlessly. It is up to the author of each type to maintain this paradigm.

For scalars (ints, pointers, doubles, etc.) copy and move are the same thing: copy the bits, don't alter the source.

Ullyot answered 16/9, 2020 at 0:6 Comment(2)
Thanks. But why is Bjarne saying "rather than copying"? That is what started my confusion.Vicentevicepresident
Move rather than copy in order to make the code more efficient. I've updated my answer to reflect that.Ullyot
D
1

The act of 'moving of an object' is analogous to the act of 'selling a house'. The object remains stationary. Only the title (ownership) changes hands.

The concept of moving an object in C++ is one of the implementations of the well known 'pass-by-reference' method. This can be explained easily by a real example.

An Internet Router is one of the best examples to describe this concept of moving an object. Suppose that a router with 4 interfaces has received a packet of data (IP packet) via one of its interfaces. Now, the router has to look up its routing table, apply security policies, apply NAT rules, etc on the packet before sending it out of one of its interfaces.

The router will create only one copy of the data packet in the memory and pass its reference to different sub-systems (Route table, NAT, Security, QoS, etc). Each sub-systme of the router will operate on the packet and pass it on to the next sub-system, till the packet gets sent out of the router, towards the destination. Memory will be cleaned up when the packet leaves the router.

In this scenario, the different sub-systems of router gain control over the same packet object at different times. The packet object remains at a single memory location throughout the processing. It never gets copied. This method of passing ownership of an object to different sub-systems / functions can be seen as 'moving the object'. However, in practice, the object had stayed where it is, but the control of object had moved across sub-systems.

(Similar to how the ownership of a house gets transferred when it is sold.)

Decal answered 16/9, 2020 at 0:49 Comment(1)
Bringing in “pass by reference” really does not seem to add value, especially as this is not how it’s generally defined, and especially now what it means in C++. Even if “pass by reference” was confusingly meant to be “call by object sharing”, it still wouldn’t be fitting..Calabrese

© 2022 - 2024 — McMap. All rights reserved.