Allanqunzi
Allanqunzi

Reputation: 3260

push back an object which has only move constructor to a vector

This is a rather general question. In this post Where does a std::vector allocate its memory? it says that vector allocates its elements in the heap by default. In C++11, there is move semantics and vector supports this. What if I have an object which has only move constructor, and I have declared this object in the stack, now I want to push_back this object into a vector, is the one being pushed back still in the heap?

An example might be pushing back a stack declared std::thread t1(someFunc) into a vector, as following

int main(){
      std::thread t1(someFunc);
      std::vector<std::thread> threads;
      threads.push_back(t1); // is the one being pushed back in the heap
                             // or in the stack? Is the answer generally
                             // true for objects which have only move
                             // constructors?
}

Upvotes: 2

Views: 1954

Answers (3)

ZunTzu
ZunTzu

Reputation: 7772

Calling a move constructor in C++11 doesn't actually move anything. It is just a mechanism to manage object life-cycle and ownership.

Calling a move constructor actually means: "copy this object, and by the way you can cannibalize any data structure already allocated for this object because I will not use it anymore".

Upvotes: 0

Cameron
Cameron

Reputation: 98746

The instance stored in the vector will always be a different object than the one you push in, even if it's moved. Moving an object merely invokes the move constructor instead of the copy constructor for the corresponding object being created in the vector.

So yes, you can push a moveable-only type into a vector, but no, it does not somehow magically transform a patch of stack space into a patch of heap space. It merely creates a new object in the vector with the contents of the object on the stack moved into it. How the contents are moved (i.e. what a move is, exactly) is up to each object to decide -- and that's what move constructors do.

The syntax for doing this might look like so:

std::vector<std::thread> threads;
std::thread t([]() { /* do something */ });

// You need `std::move` here to force the object to be treated as
// an r-value and get moved instead of trying to be copied.
threads.push_back(std::move(t));

// At this point `t` still exists (until the end of scope), but
// its contents (while valid) are indeterminate. It does not refer
// to the running thread any more.

threads.back().join();

Upvotes: 7

Mike Seymour
Mike Seymour

Reputation: 254431

Moving an object transfers state from one object to another; the two objects are separate, and at different locations, and remain separate objects at the same locations afterwards.

So the answer to the question is yes: the object in the vector is on the heap, wherever the object used to initialise it resides.

Upvotes: 3

Related Questions