Reputation: 155
I have a problem with c++ pointers
I'm a C# and VB.NET programmer, but I have converted to C++ recently, so I'm a C++ new newbie somehow
Now I'm writing a subtitle editor and I have two classes a subtitle Paragraph class containing a list of pointers to all of its lines
And a subtitle line class containing a pointer to its parent paragraph (to invoke a method in parent when line has changes )
In the subtitle paragraph class, when I delete the list of pointer to the sub lines they don't get deleted
I tested this by trying to use the pointers after deleting them and call some functions and they work!
I also used "System Monitor" in Ubuntu to tell how much memory does my application use before and after allocating space for the pointers
and I found that it gets increased after allocating memory but the space doesn't get freed after I delete the pointers
So I have a couple of questions:
1- can I have two classes each of which referencing to each other?
2- when I replace a pointer in one of the two classes with a reference does the same problem still exists
3- if I have two classes each of which referencing to each other how can I break this reference manually
I know I can use a shared pointer or weak pointer classes but I want to do it manually first
Here is a sample of my two classes to demonstrate the problem in my application
#include <iostream>
#include <stdio.h>
class B;
class A
{
public :
void setB(B *b){_b = b;cout << "set B" << endl;}
~A();
private:
B *_b;
};
class B
{
public :
void setA(A *a){_a = a;cout << "set A" << endl;}
~B(){cout <<"B is dieing" << endl;/*delete _a;*/}
private:
A *_a;
};
A::~A(){cout << "A is dieing" << endl;delete _b;}
int main()
{
getchar(); // two have some time to know how much memory does my application use before allocaing space for pointers
A *a = new A;
B *b = new B;
a->setB(b);
b->setA(a);
getchar();// two have some time to know how much memory does my application use after deallocaing the space
delete a;
delete b;
// but here,after deleting it, it's still there, not deleted! I can use it
a->setB(b);
getchar();
return 0;
}
thanks in advance
Yasser Sobhy
Upvotes: 0
Views: 539
Reputation: 4391
To answer your question "can I have two classes each of which referencing to each other?", the answer is obviously yes. But you then need to constantly think about "who owns the memory? When is this pointer valid? When is it invalid? How do I know if and when it changes?"
In C#, you never had to care because the reference counting and garbage collector built into the .Net framework took care of memory ownership and management for you, and automatically did the right thing at the right time. In C++ it's the programmer's responsibility to think about such things.
What works well in C++ is to allocate objects on the stack in the context that owns them.
int main()
{
A a;
B b;
a.setB(&b);
b.setA(&a);
return(0);
}
Now, when main() goes out of scope, both a and b will be destroyed automatically.
This can still run into the real issue you've created for yourself. Does the A class really need to keep and hold a copy of the pointer to the B? Often, A only needs the reference to B during the execution of a certain method. Instead of holding onto the copy, why not pass it in just when it's needed?
a.doesSomethingWithB(parm1, parm2, &b);
That way A doesn't have a long term commitment with B.
Keeping a copy of anything means the copy can get out of sync with the real thing. This is the reason we have the "Don't Repeat Yourself" rule (aka D.R.Y., aka the One Definition Rule.)
When I'm reviewing C++ code, I look for instances of the "new" operator, because that tells me the developer is going to manually manage the memory, and this means he or she has to be extra careful with destructors, pointers, copies of pointers, managing lifetime, all this extra stuff that will make the code more complicated. Complicated code leads to bugs.
Upvotes: 3
Reputation: 49
just because you delete a or delete b doesn't mean that the pointer is changed to null.
Look at: Why Doesn't delete reset its pointer to null
think of it as you pass the address stored in a to the delete operator.
delete frees the memory address but doesn't modify the variable holding the address.
A good tactic is
delete a;
a = null;
referencing objects after deletion is undefined behavior.
Upvotes: 0
Reputation: 2116
After having deleted an object, you could make the pointers point to NULL so you would not be able to use both of them anymore.
When you free a memory space in the heap, blocks are considered as free so they will be overwritten on any further memory allocation. But if not, you can still use it as you saw. But it is obviously not a good practice at all.
Upvotes: 1