1

As you can see, from my output results, the address of this changed during execution for me, I thought I could make use of Pointer comparison for achieving a Tree system without having a child list inside Node and I want to be able to compare parent for each element inside a nodo list for further functionality. but the main issue for it is pointer address changing, can anyone help me understand what I'm missing.

 struct Nodo{
    Nodo* parent=0;
    const char* identity;
    Component* component;
    Nodo()=default;
    Nodo(const char* uid){
        identity=uid;
    }
    Nodo(Nodo* ptr,const char* uid){
        parent=ptr;
        identity=uid;
        std::cout << "\n Address given to " << uid << "  " << ptr <<std::endl;
    }
    void Add(const char* uid,std::vector<Nodo>& objects){
        std::cout << "\n Add call in " << identity << " address sent "<< this <<std::endl;
        objects.emplace_back(Nodo(this,uid));
    }
    void GrapthUI(std::vector<Nodo>& nodes){
        ImGui::PushID(this);
        if(ImGui::TreeNode(identity)){
            ImGui::TreePop();
            ImGui::Indent();
            for(int indx=0; indx<nodes.size(); indx++){
                if(&nodes[indx]!=this){
                    if(nodes[indx].parent==this){
                        nodes[indx].GrapthUI(nodes);
                    }
                }
            }
            ImGui::Unindent();
        }
        ImGui::PopID();
    }
 }

std::vector<Nodo> node;
Main(){//in c++ file.
    node.emplace_back(Nodo("root"));
    node[0].Add("Airplane",node);
    node[0].Add("Ball",node);
    node[1].Add("Car",node);
}

Output:

 Add call in [ root ] address sent 0C8FCF88
 Address given to [ Airplane ] 0C8FCF88

 Add call in [ root ] address sent 0C920C68
 Address given to [ Ball ] 0C920C68

 Add call in [ Airplane ] address sent 0C916DE4
 Address given to [ Car ]  0C916DE4

I expected the parent pointer for Airplane and Ball to have the same address [0C8FCF88] of Root but It's different. I saw a similar post to this here with the same name but it doesn't help me nor is concerning exactly my issue.

Botje
  • 26,269
  • 3
  • 31
  • 41
Xero
  • 23
  • 1
  • 5
  • 2
    Did you take into account that a `std::vector` can relocate its members when it grows? – Botje Oct 08 '20 at 09:14
  • 1
    vector invalidates all iterators when reallocating memory – Yamahari Oct 08 '20 at 09:14
  • 1
    You are seeing this: [Effects of vector pushback on element address](https://stackoverflow.com/questions/15511731/effects-of-vector-pushback-on-element-address) – Botje Oct 08 '20 at 09:17
  • 1
    Unrelated, but the recursive call in GraphtUI will lead to an infinite recursion as soon as you have one node that passes both requirements. – Botje Oct 08 '20 at 09:24
  • can you give me a case which would lead to that? I was going to be calling GraphUI, from a single node[0] -(root) node. But there can be other cases I'm missing. – Xero Oct 08 '20 at 10:54

2 Answers2

2

If you add an element to the vector and the resulting size exceeds its current capacity, the vector needs to allocate more memory. It allocates a new memory block and moves all existing elements into this memory block, then adds the new element. The old memory block is then freed.

If you want to have stable adresses, you can use std::vector<std::unique_ptr<Nodo>>.

lars
  • 475
  • 2
  • 6
  • ... Except the child nodes will have an additional pointer to said `unique_ptr` via `parent`. Strictly speaking you should use a `shared_ptr` resp. `weak_ptr` in this situation, but we don't know what OP is using the `parent` pointer for. – Botje Oct 08 '20 at 09:23
  • 1
    I don't think that is an issue, the vector "owns" the tree, it seems like he plans to add all childs to the vector. But it's definitly worth for OP to read about the smart pointers available in C++ and think about what's best for his usecase. – lars Oct 08 '20 at 09:29
  • Yes, hence the "strictly speaking" part. If the parent pointer is only supposed to be used to provide node identity, I would allow this code to pass through code review. – Botje Oct 08 '20 at 09:31
  • understood thanks for the clarification, I did not realize this is the case for std::vector, looks like I need to do some rethinking. – Xero Oct 08 '20 at 10:50
0

This is not an issue. This behaviour is normal. The std::vector when you start allocate a piece of memory of a certain dimension. When you add an element to the vector if the memory allocated is sufficient, the address is the same ( pay attention also if the memory is sufficient but the limit is near, can be possible that the execution relocate the entire vector), neither if the memory is not sufficient, all the vector is relocated in a new space of memory larger and the precedent area of memory is freed. This behaviour can happen also when you remove an element from the vector, that resize it self to save memory.

As said by Cppreference push_back :

If the new size() is greater than capacity() then all iterators and references (including the past-the-end iterator) are invalidated. Otherwise only the past-the-end iterator is invalidated.

Zig Razor
  • 3,381
  • 2
  • 15
  • 35
  • "This is not an issue." This is wrong given his code sample. He models a tree and will have invalid pointers in it. – lars Oct 08 '20 at 09:29