heturing
heturing

Reputation: 150

How c++ manages the memory of a container in class?

In c++, when all the memory allocated to a container (say vector) is used up (and we are trying to add one more element), the memory will be reallocated. However, I was wondering that how class in c++ manages the memory for containers.

For example, I run the following code:

#include <iostream>
#include <vector>
class Test{
public:
    int i = 0;
    std::vector<int> v;
};

int main(){
    Test t;
    std::cout << "Address of t: " << &t << ", capacity of vector: " << t.v.capacity() << ", size of vector: " << t.v.size() << ", address of vector: " << &(t.v) << std::endl;

    t.v.push_back(1);
    std::cout << "Address of t: " << &t << ", capacity of vector: " << t.v.capacity() << ", size of vector: " << t.v.size() << ", address of vector: " << &(t.v) << std::endl;

    t.v.push_back(2);
    std::cout << "Address of t: " << &t << ", capacity of vector: " << t.v.capacity() << ", size of vector: " << t.v.size() << ", address of vector: " << &(t.v) << std::endl;

    return 0;
}

And the output is:

Address of t: 0x61fee8, capacity of vector: 0, size of vector: 0, address of vector: 0x61feec

Address of t: 0x61fee8, capacity of vector: 1, size of vector: 1, address of vector: 0x61feec

Address of t: 0x61fee8, capacity of vector: 2, size of vector: 2, address of vector: 0x61feec

The address of the vector is not changed. Does it mean the c++ uses a pointer to represent each data member (so address 0x61feec actually points to the address of the vector)?

Upvotes: 1

Views: 186

Answers (2)

Remy Lebeau
Remy Lebeau

Reputation: 596256

The address of the vector is not changed.

Correct, because the vector itself is not moving around in memory.

Does it mean the c++ uses a pointer to represent each data member (so address 0x61feec actually points to the address of the vector)?

Everything in memory has an address.

The std::vector class internally contains a data member that is a pointer to an array of elements. The vector::size() method reports the number of valid elements in the array, while the vector::capacity() method reports the maximum number of elements the array is allocated to hold. The vector (re-)allocates that array dynamically as needed, ie whenever the size() is equal to the capacity() when adding new elements.

Nothing in your example code is printing the address of that array itself. The vector::data() method returns a pointer to that array. Add that pointer to your logging, and you will see it change value as the capacity() changes over time, eg:

void log(const Test &t)
{
    std::cout << "Address of t: " << &t
              << ", capacity of vector: " << t.v.capacity()
              << ", size of vector: " << t.v.size()
              << ", address of vector: " << &(t.v)
              << ", address of vector data: " << t.v.data()
              << std::endl;
}

int main(){
    Test t;
    log(t);

    for(int i = 1; i <= 50; i++)
    {
        t.v.push_back(i);
        log(t);
    }

    return 0;
}

Upvotes: 1

UniversE
UniversE

Reputation: 2507

The memory is embedded into the containing class. Let's look at an easy example:

struct myvector {
   size_t size;
   void* data;
}

class Test {
   myvector v;
}

In this case, new objects of class Test will be allocated with sizeof(size_t)+sizeof(void*) bytes.

Now when it comes to resizing the vector, all that is done, is a realloc() on the memory pointed to by data.

Of course, the std::vector implementation is far more complicaten than that, but I think you get the idea.

Upvotes: 0

Related Questions