TheRocinante
TheRocinante

Reputation: 4201

Safe way to construct a vector inside a loop and return it outside that scope?

I have a code sample, and I'd like to ask you to review this and tell me if my understanding is correct. I am learning C++, and so I apologize if these questions are rudimentary. I have read about how C++ handles memory management, but I haven't found practical examples. I am trying to write some myself.

Code Sample:

std::vector<std::vector<int32_t>> containerOfVectors;
for (int i = 0; i < 2; i++) {
    std::vector<int32_t> innerVector;
    innerVector.push_back(1);
    containerOfVectors.push_back(move(innerVector));
    innerVector.push_back(2);
    innerVector.push_back(3);
    innerVector.push_back(4);
    std::cout << "innerVector " << std::to_string(i) << " contains: " << std::endl;
    for (int k = 0; k < innerVector.size(); k++) {
        std::cout << "\t" << std::to_string(innerVector[k]) << std::endl;
    }
}

for (int i = 0; i < 2; i++) {
    std::vector<int32_t> vector = containerOfVectors[i];
    std::cout << "Vector " << std::to_string(i) << " contains " << std::to_string(vector.size()) << " element(s)" << std::endl;
}
----------
Output:
----------
innerVector 0 contains: 
    2
    3
    4
innerVector 1 contains: 
    2
    3
    4
Vector 0 contains 1 element(s)
Vector 1 contains 1 element(s)

I have a (container) vector of vectors, and I am looping and creating two vectors inside the loop, which are added to the containerOfVectors. I add one element to the vector inside the loop, move it to the containerOfVectors, and then add three additional elements.

In the second loop, when I iterate containerOfVectors and print out the values, I only see 1. The values 2, 3, and 4 are not there.

My understanding of this is that the move call is copying the elements of innerVector into a new vector, and at that point innerVector becomes empty. And hence, at the end of the loop iteration, innerVector will only contain 2, 3, and 4 since only 1 was moved over. And then innerVector is destroyed.

Is that move actually a "copy", or does it "move" the same "2"? And would it (or how would it) differ if the value was a struct instead of an integer? And how can I test that myself? By printing the memory address, or can the memory address be different for the same underlying instance?

I apologize there's a lot to unpack here. Any guidance is highly appreciated.

Upvotes: 1

Views: 402

Answers (1)

Ralf Ulrich
Ralf Ulrich

Reputation: 1714

The move semantics creates new objects. It is not a copy or assignment, it is a move-constructor that is invoked. Thus, if you call move(innerVector) you actually create a new vector object as entry in containerOfVectors. This automatically contains the content/data of the original innerVector at the moment you make the call. Afterwards, the innerVector is empty, and whatever you do with it will not affect the new object inside containerOfVectors. There is no link between those two distinct objects. The memory address of an object created with move-construction is certainly always different from its original object.

This fully explains the output of your example. With any other data type inside the vector, also structs, this will be just the same.

Upvotes: 1

Related Questions