Reputation: 9678
So to illustrate my question I have made an example:
#include <iostream>
using namespace std;
struct A
{
void doSomething (){
cout << "Something\n";
}
};
struct B
{
A a;
A *getA ()
{
return &a;
}
};
int
main ()
{
B *b = new B ();
A *a = b->getA ();
// POINT 1
if (nullptr != a)
{
a->doSomething ();
}
delete b;
b = nullptr;
// POINT 2
if (nullptr != a)
{
a->doSomething ();
}
return 0;
}
This compiles and runs without errors on my machine, but if you inspect the code, really there is a problem of a dangling pointer on the lines following the comment marked "POINT 2".
Since b
was deleted, then a
is now invalid (since it was deleted by dtor of b
).
So I could use a shared pointer to remedy this, but that would keep the instance of a
around even after b
was deleted, and also I would not be able to allocate a
on the stack. These are two things I want to avoid. Instead I simply want to know if a
is still valid.
I could also have used a unique pointer but then I could only have one single instance of a
which is not what I want either, I want many copies of the pointer to a
.
So is there some existing pointer/reference type that would allow me to do this? Are there any reason why this is a good/bad idea?
Upvotes: 2
Views: 48
Reputation: 385264
The best way is to not expose a
.
Your B
is the interface. Give it the functions you need to perform. Have it go on to invoke whatever it needs to invoke on the a
in order to make that happen.
Then remove getA()
, and make a
private.
Now it's completely encapsulated and the calling scope cannot arse around with it like this!
No need for pointers or dynamic allocation; just good, old-fashioned OOP.
Upvotes: 1
Reputation: 26146
You have just discovered the wonders of ownership semantics :)
How to solve this problem depends on the design of your application: what you need and what you are trying to achieve.
In this case, if you really want to share ownership of an object, use std::shared_ptr
which keeps a reference count of how many pointers are left, so that the last deletes the object; possibly std::weak_ptr
if you only need to check if the object is still alive but don't want to keep it alive longer than needed.
However, do note that (ab)using shared pointers may be a sign of a bad design.
By the way, your A a;
member is not allocated in the stack (i.e. the title is wrong).
Upvotes: 3
Reputation: 44268
Only viable solution using standard library that come in mind is to use std::weak_ptr() - it will allow to check object validity without holding it's ownership. That comes with price - you have to maintain ownership of it with std::shared_ptr
. Though it is possible to create std::shared_ptr
to an object with automatic storage duration and noop deleter I would do that only if I really need that as such method is error prone and defeats the purpose of a smart pointer.
Upvotes: 3