-1

I have made a class Graph when I have made a pointer in private access in the class named visited. In the constructor I have initialized the array with zero at all places but when I am checking if all the values are zero in another method ,It is showing garbage values in the array but when I print it in the constructor itself then it showing all zeroes.

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

class Graph {
private:
  int vertices,edges;
  vector <list<int>> graph;
  vector <int> vs;
  int *visited;
public:
  Graph (int vertices)
  {
    this->vertices = vertices;
    list <int>l;
    for (size_t i = 0; i < vertices; i++) {
      graph.push_back(l);
      vs.push_back(i);
    }
    edges=0;
// #######  made a new array, initialized all values with zeroes and assigned it to the instance variable visited  #########
    int a[vertices]={0};
    this->visited = a;
// ########  in the constructor it is showing correct values below  #######
    for (size_t i = 0; i < vertices; i++) {
      std::cout << this->visited[i] << ' ';
    }
    std::cout << '\n';
  }
  virtual ~Graph ()
  {

  }
  void showList()
  {
// just printing the graph in the form of adjacency list 
// it is working fine
    for (size_t i = 0; i < vertices; i++)
    {
      list <int>::iterator p = graph[i].begin();
      std::cout << i ;
      for (; p != graph[i].end() ; p++)
      {
        std::cout << " -> " << *p ;
      }
      std::cout << " -> NULL" << '\n';
    }
// ########  when I am checking the values here then it is printing garbage values 
    for (size_t i = 0; i < this->vertices; i++) {
      std::cout << this->visited[i] << ' ';
    }
  }
  void addEdge(int source, int destination)
  {
    graph[source].push_back(destination);
  }
};

int main()
{
  Graph g(6);
  g.addEdge(0,1);
  g.addEdge(0,2);
  g.addEdge(1,0);
  g.addEdge(1,3);
  g.addEdge(1,4);
  g.addEdge(2,0);
  g.addEdge(2,4);
  g.showList();
  return 0;
}

when i call the showList method the it should print the adjacenct list and all zeroes(contents of array named visited)

Martin York
  • 257,169
  • 86
  • 333
  • 562
sha algo
  • 3
  • 2
  • `int a[vertices]={0};` is local to the constructor (and not valid standard C++). It is destroyed after the constructor is finished, leaving you with a dangling pointer – UnholySheep Jan 04 '19 at 21:25
  • 4
    Using `std::vector visited;` would be far easier. You already use `std::vector` in the same class. I don't see why `visited` needs to be any different. – François Andrieux Jan 04 '19 at 21:25

1 Answers1

1

I have made a class Graph.

Yes you have.

class Graph {

I have made a pointer in private access in the class named visited.

Yes you have.

private:
  int *visited;

In the constructor I have initialized the array with zero at all places.

Yes you have.

int a[vertices]={0};

But I would note that this is a variable that is local to the constructor. It is not visible to any other methods. Also when the constructor finishes the lifespan of this object ends. Any attempt to accesses this array after its lifetime ends is undefined behavior. So accessing this by some sneaky mechanism (like savings its address in a pointer) is going to cause bad things to happen.

Here you are doing something sneaky (and very bad):

this->visited = a;

but when I am checking if all the values are zero in another method

You are accessing the array through a pointer visited. This is pointing to an array that no longer exists because the array is local to another function.

    std::cout << this->visited[i] << ' ';  // This is broken code.

It is showing garbage values in the array

You are very unlucky. It would have been nicer if the program had crashed and made it more obvious that something bad is happening. Unfortunately you have discovered that undefined behavior can do anything (including simply return some random values).

but when I print it in the constructor itself then it showing all zeroes.

It is still valid in the constructor so accessing it is not a problem.

So what is the solution.

In general pointers you should avoid pointers (especially when brand new). You need to get some basic concepts down first.

In this case simply replace:

 int*   visited;

With

 std::vector<int> visited;

In the constructor fill this with the appropriate zero values.

Community
  • 1
  • 1
Martin York
  • 257,169
  • 86
  • 333
  • 562
  • can you suggest away to me to initialize the array with all zeroes – sha algo Jan 04 '19 at 21:39
  • @shaalgo Done. Use a std::vector as a class member. – Martin York Jan 04 '19 at 21:40
  • thanks sir for the solution but can it be done using a simple array – sha algo Jan 04 '19 at 21:42
  • @shaalgo Not really. Technically your declaration `int a[vertices]` is illegal (your compiler excepts it as an extension). The problem is that the size `vertices` should be known at compile time for it to be legal. `std::vector<>` is a much better than normal arrays (as even using `int visited[LARGENUMBER];` has a set of problems associated with it that `std::vector` solves. – Martin York Jan 04 '19 at 22:14