MTLaurentys
MTLaurentys

Reputation: 221

Losing references to objects inside containers

I am struggling to fix a piece of code, even though I believe I know the cause. I did search a lot on Stack Overflow and many people had similar issues (and good answers were provided), but still, I am not sure I understand the problem with my code.

I tried giving a smaller example, but the structure I have is not simple by itself. I hope the following is simple enough.

My objective on the excerpt:

segment::segment (point &pt1, point&pt2, int i) {
   s = &pt1; e = &pt2; ind = i; // point *s, point *e, int ind
}
event::event (segment &s, point &pt, int tp) {
   seg = &s; type = tp; p = &pt; //segment *seg, int type, point *p
}
void pre_process (int size, std::vector<point>& pts, std::vector<event>& evts,
        std::vector<segment>& segs) {
    float x, y;
    for (int i = 0; i < size; ++ i) {
        std::cin >> x >> y;
        pts.push_back({x,y});
    }
    for (int i = 0; i < size; ++i) {
        int j = (i+1)%size;
        if (cmpXY(pts[i], pts[j]))
            segs.push_back({pts[i], pts[j], i});
        else
            segs.push_back({pts[j], pts[i], i});
        evts.push_back({segs[i], *segs[i].s, 0});
        evts.push_back({segs[i], *segs[i].e, 1});
        std::cout << 2*i << "\n";
        std::cout << segs[i].s << "\n";       //ALWAYS EQUAl
        std::cout << evts[2*i].seg->s << "\n";
    } // LINE X
    for (int i = 0; i < size; ++i) { //LINE Y
        std::cout << 2*i << "\n";
        std::cout << segs[i].s << "\n";        //DIFFERENT SOMETIMES
        std::cout << evts[2*i].seg->s << "\n";
    }

So, the problem is that some of addresses my objects are pointing to change from LINE X to LINE Y. In particular, pts and segs remain the same.

From what I know and from what I understood here or here I cannot get the reference to an object on the stack of any function (my for loop, for example). However, I believe the lifetime of the object on the container is the same as the container itself. It makes me believe that all objects I push_back() should persist through the function pre_proccess and the function that is calling it.

Upvotes: 0

Views: 61

Answers (2)

ichramm
ichramm

Reputation: 6632

It looks that the vector resize itself and had to be relocated (which will invalidate all iterator references).

Try to use std::vector::reserve before processing:

void pre_process (int size, std::vector<point>& pts, std::vector<event>& evts,
        std::vector<segment>& segs) {
    pts.reserve(size);
    evts.reserve(size);
    segs.reserve(size);

    float x, y;
    for (int i = 0; i < size; ++ i) {
        std::cin >> x >> y;
        pts.push_back({x,y});
    }
    for (int i = 0; i < size; ++i) {
        int j = (i+1)%size;
        if (cmpXY(pts[i], pts[j]))
            segs.push_back({pts[i], pts[j], i});
        else
            segs.push_back({pts[j], pts[i], i});
        evts.push_back({segs[i], *segs[i].s, 0});
        evts.push_back({segs[i], *segs[i].e, 1});
        std::cout << 2*i << "\n";
        std::cout << segs[i].s << "\n";       //ALWAYS EQUAl
        std::cout << evts[2*i].seg->s << "\n";
    } // LINE X
    for (int i = 0; i < size; ++i) { //LINE Y
        std::cout << 2*i << "\n";
        std::cout << segs[i].s << "\n";        //DIFFERENT SOMETIMES
        std::cout << evts[2*i].seg->s << "\n";
}

Upvotes: 1

Jarod42
Jarod42

Reputation: 217085

push_back on vector (might) invalidate previous reference/iterator.

it happens in the loop there

if (cmpXY(pts[i], pts[j]))
    segs.push_back({pts[i], pts[j], i});
else
    segs.push_back({pts[j], pts[i], i});
evts.push_back({segs[i], *segs[i].s, 0});

you have to reserve enough place in segs to avoid reallocation (or change the logic).

Upvotes: 1

Related Questions