Reputation: 2593
If I reserve vector with certain size, then I have a loop where I take local variable and then emplace_back(std::move(local_object))
, since std::move
transfer the ownership of the memory. Will the vector have the elements with consecutive locations?
Upvotes: 0
Views: 618
Reputation: 14673
Those are not rules of language, but architectural concepts:
You have to remember that storage occupied by object is not owned by said object. It is owned by something hierarchically higher. That can be another object or process, or a function in case of automatic storage.
Taking ownership of allocated dynamic memory supposes to take control of pointer returned by a new expression. Once gained it controlled until by holder of that value and to stop existing it should be "deleted". Otherwise it will be "lost", leading to so-called memory leak. But it's preferred to consider term "ownership of resource" to abolish details of implementation and designate that prticular entity has access to said resource and controls its "life".
To analyze expression emplace_back(std::move(local_object))
one should consider that
Vector doesn't own resources of stored objects. It takes owner of resource used to store objects.
If a stored object of type T owns some resources, they are NOT passing ownership to container. They continue own them.
emplace_back
constructs a new object of type T in memory location owned by vector
if there is available space. Otherwise it would reallocate vector
's storage to gain required resource. Arguments of emplace_back
are used as arguments of constructor for type T.
std::move
doesn't move anything. It is a standardized mnemonic for a xvalue expression, equivalent to static cast for result of expression used as its argument to a rvalue reference type.
As argument of emplace_back
is an rvalue reference to original object of type T, so called "move constructor" is invoked. If constructor was defined for the type T by user, then it is user's responsibility for what action were done after vector finished allocation.
If no user-defined move and copy constructors and assignment operators were defined for T as well there is no user-defined destructor, then move constructor is implicitly declared by compiler. Implicitly declared move constructor follows defined semantic for all members, in order of declaration:
Implicitly declared move constructor is defined as deleted if T contains any non-static member of T that is not movable, direct or virtual base class that is not movable, or if T is a union-like class and has a member with user-defined move constructor.
Ability to be moved implies presence of access to unambiguous and not deleted move constructor in present context.
Therefore emplace_back
would result in transfer of ownership from original object of type T to newly constructed object, only if user had defined move constructor for object of type T or any of its sub-objects and whole conglomerate is movable. If that requirement is not met, then construction of new object by call of copy-constructor will be considered. Otherwise it is nothing but a shallow copy.
Upvotes: 0
Reputation: 117798
A vector always stores elements in consecutive locations.
When you add new elements, the vector
may need to allocate new memory and relocate the data in order to make the elements fit in consecutive locations.
The reserve
step makes one memory allocation and you are guaranteed to be able to add the number of elements you've reserved space for without relocations.
std::move
doesn't move anything. It's used on local_object
to indicate that it may be moved from which makes the move constructor eligable. It's the move constructor that does the actual transfer of ownership.
If you have raw pointers in your object you must write the copy and move constructors yourself (as well as the copy and move assignment operators). See the rule of 5.
Upvotes: 2
Reputation: 155566
The vector
is always using consecutive (contiguous) memory locations. But if std::move
is actually helping, odds are it's because your objects don't store their own memory entirely locally (with some of the data being stored in dynamically allocated memory), and that non-local memory will remain non-local (the pointers to it are moved over as part of the move construction, but where they point remains unchanged).
In short, the parts that don't benefit from move
will be contiguous, and the parts that do benefit from move
will remain where they were.
Upvotes: 2
Reputation: 18248
It moves the contents of the memory of local_object
, it does not magically move the memory itself. The vector
has its own storage which is always continuous.
Upvotes: 3