Home > Software design >  C Vector content is being deleted?
C Vector content is being deleted?

Time:05-19

I've been trying to create a directed graph following https://www.youtube.com/watch?v=V_TulH374hw

class Digraph {
public:
    Digraph();

    void addNode(Node);
    void addEdge(Edge);

    void print();

private:
    //This is a vector which contains a node source and a vector of node destinations
    vector< tuple< Node, vector<Node>>> nodes;
};

but after I add 2 nodes and a Edge it seems like the vector with the destinations is beeing emptied

void Digraph::addEdge(Edge e){
   Node src = e.getSrc();
   Node dest = e.getDest();

   for(auto node : nodes){
       if(get<0>(node).getName() == src.getName()){
           get<1>(node).push_back(dest);
           //cout << "added conection " << get<0>(node).getName() << " -> " << get<1>(node).back().getName() << " now "  << get<0>(node).getName() << " has " << get<1>(node).size() << " destinations" <<"\n";
           return;
       }
   }

   cout << "node " << src.getName() << " does not exist \n";
   return;
}

void Digraph::print(){
   for(auto node : nodes){
       get<0>(node).print();
       cout << " has " << get<1>(node).size() << " destinations";
       cout << "\n";
       for(auto destination : get<1>(node)){
           cout << "\t->";
           destination.print();
           cout << "\n";
       }
}

}

In main.cpp I add the nodes and the edge

graph.addNode(NY);
graph.addNode(CHICAGO);

graph.addEdge(road);
graph.print();

It ends up adding the edge succesfully but when it prints the final result it does not recognize the edge it just added

added conection NY -> Chicago now NY has 1 destinations
NY has 0 destinations
Chicago has 0 destinations

When tried with more Nodes and Edges I realized it never adds more than one Edge, maybe it has to do with how i defined the class? vectors is not the choice?

CodePudding user response:

Your auto in the for loop needs to be a reference (auto&), and after the code I'll tell you why.

void Digraph::addEdge(Edge e){
   Node src = e.getSrc();
   Node dest = e.getDest();
   // use references here
   for(auto& node : nodes){
       if(get<0>(node).getName() == src.getName()){
           // now this modifies the original, not a copy
           get<1>(node).push_back(dest);
           //cout << "added conection " << get<0>(node).getName() << " -> " << get<1>(node).back().getName() << " now "  << get<0>(node).getName() << " has " << get<1>(node).size() << " destinations" <<"\n";
           return;
       }
   }

   cout << "node " << src.getName() << " does not exist \n";
   return;
}

The entire point of this function is to change the nodes in some way. If you iterate over them with for (auto node : nodes) you are getting a copy of each node. It's the same as Node node : nodes, the auto doesn't make a difference. You then call push_back on this copy, which gets destroyed as soon as the next loop iteration comes up.

Effectively, your original stays entirely untouched since you only take copies of it's member nodes, not references.

If you use a reference here like I did, you take a reference to each node in the nodes vector, and modify the reference, which modifies the original.

  • Related