简体   繁体   中英

How vector allocate memory

Hii I know that vector allocated contiguous fixed memory when it needs to push_back some items.And if its not able to fit into it it will alllocate new memory and copy old values into it and delete the old memory. If that is the case how the following code works

#include<iostream>  
#include<vector>  
using namespace std;   

class Test   
{
public :   
    int val;   
    Test()   
    {
        val=0;   
    }   
};   


int main()   
{
    vector<Test>vec;   
    Test t[10];   
    for (int i=0;i<5;i++)   
        vec.push_back(t[i]);   
    cout<<vec.capacity()<<endl; //printing 8   
    Test* obj=&vec[2];   
    obj->val=2;   
    cout<<obj<<endl;   
    for (int i=0;i<5;i++) //Adding 5 elements more 
        vec.push_back(t[i]);   
    Test* obk=&vec[2];    
    cout<<obk->val<<endl;    
    cout<<obj->val<<endl;    
    cout<<obj<<endl;  
    cout<<obk<<endl;  
}  

Here if you see obj is taking pointer of vec[2] which value in my machine is coming 0x8bcb048 .Then I am inserting 5 more items so vector will allocate new memory.Now if i am taking obk from vector[2] its coming different address 0x8bcb070 . But if i try to acess i with the help of obj its not giving any problem.Any reason ?

But if i try to access it with the help of obj its not giving any problem. Any reason?

This is undefined behavior - the fact that it appears to work is simply due to luck (whether good or bad luck is matter of opinion).

Essentially you're dereferencing a 'dangling' pointer. and just like if you dereference a pointer to a block of memory that's been freed, you simply read out old, stale data that happens to look like it has reasonable values. or you might read out something that appears to be garbage. Or you might cause a segfault.

One thing is for certain - it's a bug, whether it seems to act like one or not.

When a vector reallocates, all iterators, pointers and references that you obtained prior to the reallocation are invalidated. Using them leads to undefined behavior, which includes "apparently not giving any problems".

To visualize the problem, you can insert debug outputs in the constructors and the destructor. You could also log which objects exist at any point in time:

class Test;

std::set<Test*> valid_Test_objects;

class Test
{
    int val;

public:

    Test() : val(0)
    {
        valid_Test_objects.insert(this);
        std::cout << "constructed Test object @ " << this << std::endl;
    }

    Test(const Test& that) : val(that.val)
    {
        std::cout << "constructed Test object @ " << this << std::endl;
        valid_Test_objects.insert(this);
    }

    ~Test()
    {
        std::cout << "destructing Test object @ " << this << std::endl;
        valid_Test_objects.erase(this);
    }

    int value()
    {
        std::cout << "  accessing Test object @ " << this << std::endl;
        if (valid_Test_objects.find(this) == valid_Test_objects.end())
        {
            abort();
        }
        return val;
    }
};

int main()
{
    std::vector<Test> vec;
    vec.reserve(3);

    Test x;
    vec.push_back(x);
    Test* p = &vec[0];
    std::cout << p->value() << std::endl;

    std::vector<Test>::size_type cap = vec.capacity();
    while (cap == vec.capacity()) vec.push_back(x);

    std::cout << p->value() << std::endl;
}

Unfortunately, we should not even try to call p->value() when p is invalid. Enjoy your stay at undefined behavior land ;-)

vectors are dynamic arrays. You are right when they overflow they are reallocated someplace else and all earlier initialized pointers/ iterators( which generally for vectors are also implemented as pointers, although the standards don't require it)/ address references become invalid. and earlier held memory space is freed finally.

Here is how events occur in simplistic terms:

  1. currently available space is insufficient.

  2. new memory space is acquired ( k times(generally k=2) as large as original memory size)

  3. current array is copied to new memory locations

  4. old = current; current = new; { this ensures atomicity for single insertions}

  5. old memory is freed.

Notice that old memory location's data is not destroyed or reset. So when the resources are needed again that might or might not be reused. But the original memory location that you have is a false location and must be avoid always.

If you're asking why there's no crash when you try to access 'obj' then I would say you should try to run it in Release mode and see. In any case, obj should not be accessible, as the pointer that was returned by &vec[2] was invalidated when the vector increased its capacity. It could still be pointing to some random junk that happens to be allocated to your processes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM