I'm having trouble understanding how to use dynamic allocation with constructors.
I use in my code a class named graph (which is just a bool 2-d matrix representing the edges between the nodes) with the following constructor/destructor (there others methods, but I dont think it's relevant here) :
class graph{
private:
bool** edges;
int size;
public:
graph(int size = 0):size(size){
edges = new bool*[size];
for (int i = 0; i < size; i++){
edges[i] = new bool[size];
}
}
~graph(){
for(int i = 0; i < size; ++i) {
delete [] edges[i];
}
delete [] edges;
}
//others methods
};
In my main, I want to use dynamic allocation :
int main()
{
int size;
cout << "Enter graph size :" << endl;
cin >> size;
graph g1 = new graph(size);
//some processing code
return 0;
}
Howewer, I get an error on the instantiation (ie new graph(size) ) :
invalid conversion from 'graph*' to 'int' [-fpermissive]
I don't really get what is going wrong, and I'm pretty sure it's a syntax I have already seen in others places.
Actually, I dont really get how memory allocation works with the creation of object.
Here, I use new in my constructor to create the bool 2d-matrix, so it's going to the heap, no ? But if I instanciate the object using the following static instruction : graph g1(const_size);
Then it's not suppose to going to the stack ?
Thank you in advance for your answers.
EDIT
Just one last question :
graph *g1 = new graph(size);
is storing g1 (pointer) on stack, but the object is created on the heap.
graph g1(size);
is creating object on the stack, and g1 is a reference to it.
But in any case, the matrix edges would be on the heap ? Or in the second case it would somehow end on the stack ?
The error is here:
graph g1 = new graph(size);
This should be:
graph *g1 = new graph(size);
The reason is following:
new graph(size)
is creating new graph
object and it is returning a pointer to it (with graph*
type), and:
graph g1 = ...
is trying to convert that to object to int
(in order to call graph(int)
constructor) - so the error is invalid conversion from 'graph*' to 'int'
.
Now, I suppose this is some kind of exercise, as you shouldn't use allocation on heap in this example. But if you use it anyway, don't ever forget:
delete g1;
Actually, I dont really get how memory allocation works with the creation of object.
graph *g1 = new graph(size);
is storing g1
(pointer) on stack, but the object is created on the heap.
graph g1(size);
is creating object on the stack, and g1
is a reference to it.
P.S. Avoid this:
graph g1 = graph(const_size);
This will first create evaluate right side of the statement and it will temporary graph
object, and it will use copy-constructor to initialize g1
.
But for example, if I want a program who can deal with various graph size, without recompiling it each time I want to work with a different size, I would need something like that, no ?
No, you can use stack allocation for this (I've just noticed that in your example, you're using const_size - parameter to the constructor of object allocated on stack doesn't need to be constant):
int size;
std::cout << "Enter size: ";
std::cin >> size;
graph g1(size);
Yes, dynamic allocation is not needed here, I just did that code to practice myself. But it would be necessary if I wanted to work with various sized graph without recompiling, no ?
No, look at the example right above this - stack allocated object with variable size - without recompiling.
I thought we were not supposed to call the destructor ourselves and that it was going to be called anyway when we go out of scope ? (I even read that it was actually bad to call it in some cases, as it might be calling it a second time)
That's true in case of stack allocated objects - the destructor will be called at the end of the scope. However, if you allocate object on heap, the destructor is not called until you call delete
.
But in any case, the matrix edges would be on the heap ?
edges = new bool*[size];
for (int i = 0; i < size; i++){
edges[i] = new bool[size];
}
Yes, the entire matrix is allocated on heap.