Is there a standard way of maintaining a weak pointer to a parent (which is created using a shared pointer) in a child object in C++?
Essentially, I need to implement something on the lines of the following:
Class B;
Class A
{
...
private:
B m_b;
};
Class B
{
....
public:
void SetParentPtr(const boost::shared_ptr<A>& a)
{
m_parentPtr = a;
}
private:
boost::weak_ptr<A> m_parentPtr;
};
In the above all instances of class B need to hold a weak pointer to their parent (i.e object of class A). Class A objects are instantiated using a shared_ptr. I can think of a solution that uses a null deleter. But is that a standard way of doing something like this?
What you are doing above is explicitly supported by weak_ptr and shared_ptr, what happens when you try it? To be more precise, do what you are doing, without the null deleter, and then you use the standard behaviour on the weak_ptr to convert it to a shared_ptr as needed:
boost::shared_ptr<X> it=myWeakPtr.lock();
if (it)
{
// if the conversion succeeded, then the parent instance is still alive
}
There is an implicit conversion to weak_ptr, so you can use
void SetParentPtr(boost::weak_ptr<A> a) { }
directly.
check also boost::shared_from_this so the parent can give a pointer to himself without storing a weak_ptr explicitly.
Otherwise, this seems like a normal way to have a back-pointer. Just check whether there is a real added value in using back-pointers.
I would try to do something like this:
class A
{
A(){};
public:
static boost::shared_ptr<A> Create()
{
boost::shared_ptr<A> newPtr(new A());
newPtr->m_self = newPtr;
return newPtr;
}
// ...
void CreateChild()
{
m_childPtr = B::Create(m_self);
}
private:
boost::shared_ptr<B> m_childPtr;
boost::weak_ptr<A> m_self;
};
class B
{
B(){};
public:
static boost::shared_ptr<B> Create(boost::shared_ptr<A> ptrA)
{
boost::shared_ptr<B> newPtr(new B());
newPtr->m_parentPtr = ptrA;
return newPtr;
}
boost::weak_ptr<A> m_parentPtr;
};
Related
My c++ code has to work with an underlying c-library. I have a c++ object that looks somewhat like this:
template <typename T>
class MyClass
{
public:
explicit MyClass(int x)
: mVar(x)
{
}
private:
int mVar;
};
Later in my c++ code I do the following:
auto p = new MyClass<int>(10);
call_c_lib_function((void*) p);
The c function saves the pointer 'p' in a larger c-structure. Later when the large
c object is getting destroyed, it invokes the delete handler.
void
c_delete_handler(void* data)
{
// data is holding the pointer value 'p' from above.
}
Since the object is getting destroyed, I need to free the object that allocated.
Per the c++ spec, 'delete void_ptr' is undefined since it doesn't know how to
invoke the appropriate destructor. How do I invoke delete on the appropriate
template object?
One solution I could think of was to create a wrapper structure around my MyClass pointer.
struct Wrapper {
enum template_type {
template_int,
template_double,
template_string,
...
};
int template_type;
void* obj_ptr;
};
before callign the call_c_lib_function, I'd do the following:
auto p = new MyClass<int>(10);
auto w = new Wrapper()
w.template_type = Wrapper::template_int;
w.obj_ptr = (void*) p;
call_c_lib_function((void) w);
and now in the delete handler, I can do the following:
void
c_delete_handler(void* data)
{
Wrapper* w = (Wrapper*) data;
switch (w->template_type) {
case Wrapper::template_int:
delete (MyClass<int>*) w->obj_ptr;
break;
case Wrapper::template_double:
delete (MyClass<double>*) w->obj_ptr;
break;
...
}
}
Is this a correct approach? is there a better alternative?
Would appreciate any inputs. Thanks.
Instead of using Wrapper, use a base class, if that's an option.
class MyBase
{
public:
virtual ~MyBase() {};
};
template <typename T>
class MyClass : public MyBase
{
public:
explicit MyClass(int x) : mVar(x) {}
private:
int mVar;
};
and then
void c_delete_handler(void* data)
{
Base* basePtr = reinterpret_cast<Base*>(data);
delete basePtr;
}
This approach obviates the need for keeping track of whether MyClass was instantiated using int, double, std::string, or ....
On my work I have met with one bug which can be described as follows.
There are two classes, class A and class B:
class A
{
public:
void print(){}
};
class B
{
A* a;
public:
void init(A* _a) {
a = _a;
}
void PrintWithA()
{
a->print();
}
};
A* a;
B* b;
b->init(a);
// some code .....
delete a; // line 1
a = NULL;
// some code .....
b->PrintWithA(); // line 2
Object "b" doesn't know nothing about state of object "a". In line 1 "a"object has been deleted but on line 2 we continue to use it. When there are a lot of code it is very easy to make such mistake.
My question is the following - which approch to use to avoid some mistakes? I guess I could use observer pattern - but I think it is unjustifiably expensive solution.
Thank's.
You should use a weak ptr (http://en.cppreference.com/w/cpp/memory/weak_ptr)
basically you can provide class B with a weak ptr of A.
whenever comes time to access A, you can try to lock the weak ptr to see if it's still valid.
#include <memory>
class A
{
public:
void print(){}
};
class B
{
std::weak_ptr<A> a;
public:
void init(std::weak_ptr<A> _a) {
a = _a;
}
void PrintWithA()
{
if (auto spt = a.lock()) {
spt->print();
}
}
};
int main()
{
std::shared_ptr<A> a = std::make_shared<A>();
std::unique_ptr<B> b = std::make_unique<B>();
b->init(a);
// some code .....
a = nullptr;
// some code .....
b->PrintWithA(); // line 2
return 0;
}
To guard against that, either B needs to take ownership of the lifetime of A when the object B is constructed, or you need to make A reference counted.
C++11 I think has the concept of a shared pointer which maintains the references and will prevent the object A from being deleted if someone has a reference. See std::shared_ptr
If you are not using C++11 there is boost::shared_ptr which does essentially the same thing. But you need the boost library which I personally prefer not to use, but it's up to you.
Use them like this:
typedef std::shared_ptr<A> A_ptr;
A_ptr a = new A();
class B
{
A_ptr a;
public:
void B(A_ptr _a) {
a = _a;
}
void PrintWithA()
{
a->print();
}
};
Otherwise you could put something together yourself. Something along the lines of:
class A
{
public:
A(){
ref_count = 1;
}
void print(){}
void grab() {
ref_count++;
}
void release() {
ref_count--;
if (ref_count <= 0)
~A();
}
private:
int ref_count;
~A(){
delete this;
}
};
Inside B you'd assign the pointer and call grab();
Rather than call delete (which wouldn't work because it's private) you'd call
a->release() on the pointer.
Now this is not particularly fantastic because you can't use this form:
A a;
So it's not ideal. But if you're using some compiler that doesn't have a shared_ptr and you don't mind the limitation you may use this or a form of it. In general, use shared_ptr.
First of all, the line that says A* a; should probably be A* a = new A;.
In c++ you need to encode this awareness explicitly, it's not done automatically.
One thing you can do is check if _a is NULL inside PrintWithA, but this won't work if you make sure that you always set your pointers to NULL after delete[]ing them (which you've done)
Consider following code:
#include <stdio.h>
#include <memory>
class Sub{};
class SubImpl : public Sub {};
class A{
public:
A(Sub & sub) : sub(sub){}
void doSomething(){
// ...
};
private:
Sub & sub;
};
std::unique_ptr<A> factory(){
SubImpl sub;
return std::unique_ptr<A>(new A(sub));
}
int main(){
auto a = factory();
a->doSomething();
}
This code have problem - Sub object lifetime is not same as A object, and A::sub reference is dangled.
In order to fix this, I can do:
pass by value
pass by const reference
use unique_ptr / shared_ptr or to use raw pointer
Is there any other way I can fix this?
Use unique_ptr if the object sub is used solely to create only one A object. Use shared_ptr otherwise.
class Sub{};
class SubImpl : public Sub {};
class A{
public:
A(std::unique_ptr &&sub) : sub(std::move(sub)){}
void doSomething(){
// ...
};
private:
std::unique_ptr sub;
};
std::unique_ptr<A> factory(){
auto sub = std::make_unique<SubImpl>();;
return std::make_unique<A>(std::move(sub));
}
int main(){
auto a = factory();
a->doSomething();
}
It seems you have two choices, either the lifetime of SubImpl is controlled by A in which case I see no alternative to using a pointer, preferably a unique_ptr, like bolov has shown. And I don't think there is anything particularly wrong with that.
Or the lifetime of SubImpl is controlled by something outside of A in which case you can use references.
For example, you could change the factory so that it is an object that owns the SubImpl. Here is a simplistic example:
// definitions of Sub, SubImpl and A as before...
class SubOwner {
SubImpl sub;
public:
A createA() const {
return A(sub);
}
};
int main(){
SubOwner so;
auto a = so.createA();
a.doSomething();
}
That's fine if you only want one SubImpl but it is possible that you want to use your factory to create many As and each A should have a reference to a different SubImpl. In which case you could have an object that owns a collection of SubImpl:
class SubOwner {
// Using deque instead of vector to avoid reference invalidation.
// Could use vector if you knew how many SubImpl you need up front.
std::deque<SubImpl> subs;
public:
A createA() const {
subs.emplace_back();
return A(subs.back());
}
};
int main(){
SubOwner so;
auto a1 = so.createA();
auto a2 = so.createA();
a1.doSomething();
a2.doSomething();
}
Providing SubOwner and A are themselves owned by the same object or local to the same scope then you can guarantee that the lifetime of SubImpl will be the same as A.
I'm relatively new to C++ and smart pointers as I primarily use C#. I've been through heaps of questions here about the correct usage of unique_ptrs and I think I understand that smart pointers are all about ownership and who will take responsibility for deleting the memory held by the pointer when it goes out of scope.
That said, it the below example correct? Parent will always be the owner of it's children and manage the child's lifetime. However, if another class needs to hold a child, and will always live less than the child, is it ok for that class to hold a raw pointer to the child?
class ChildTypeA;
class ChildTypeB;
class Parent
{
public:
ChildTypeA* createChildA()
{
ChildTypeA *aPtr = new ChildTypeA(/* pass this to constructor */);
typeAChildren.push_back(std::unique_ptr<ChildTypeA>(aPtr));
return aPtr;
}
ChildTypeB* createChildB()
{
ChildTypeB *aPtr = new ChildTypeB(/* pass this to constructor */);
typeBChildren.push_back(std::unique_ptr<ChildTypeB>(aPtr));
return aPtr;
}
void somethingCalledByChildA()
{}
void somethingCalledByChildB()
{}
private:
std::vector<std::unique_ptr<ChildTypeA>> typeAChildren;
std::vector<std::unique_ptr<ChildTypeB>> typeBChildren;
};
class ChildTypeA
{
public:
ChildTypeA() {} // parameterless constructor purely for single file example
ChildTypeA(Parent *parent) : owningParent(parent)
{}
void notifyParentOfSomethingA()
{
owningParent->somethingCalledByChildA();
}
void doSomethingOnThisChild()
{}
private:
Parent *owningParent;
};
class ChildTypeB
{
public:
ChildTypeB() {} // parameterless constructor purely for single file example
ChildTypeB(Parent *parent) : owningParent(parent)
{}
void notifyParentOfSomethingB()
{
owningParent->somethingCalledByChildB();
}
private:
Parent *owningParent;
};
class SomeOtherClassThatWantsAChildAAndWillAlwaysLiveShorterThanChildA
{
public:
SomeOtherClassThatWantsAChildAAndWillAlwaysLiveShorterThanChildA(ChildTypeA *child) : childNotOwnedByMe(child)
{}
void doSomething()
{
childNotOwnedByMe->doSomethingOnThisChild();
}
private:
ChildTypeA * childNotOwnedByMe;
};
So then code somewhere would do something like:
ChildTypeA *a = someInstanceOfParent->createChildA();
auto x = new SomeOtherClassThatWantsAChildAAndWillAlwaysLiveShorterThanChildA(a);
This example is correct, unique_ptr is all about ownership, and this doesn't prevent referencing the raw pointer from other class, the things that need to be kept in mind are:
1) Check the raw pointer before using.
2) Don't invoke delete on the raw pointer.
Allow me to give some background. I have an abstract class, Foo.
class Foo {
public:
virtual void bar() = 0;
}
I have two classes that inherit from this class.
class FooOne : public Foo {
public:
void bar();
}
and
class FooTwo : public Foo {
public:
void bar();
}
Now in a completely different class, I want to create an array in a function that can hold instances of one of these two classes. The problem that I'm running into is that I cannot create an array with a dynamic type like this, can I? I'm used to Objective-C where I can create an object of type id.
Ideally, this is what I was looking for (pseudocode):
void someFunction(FooType type) {
class aClass = (type == FooTypeOne ? FooOne : FooTwo);
vector<aClass> container;
// Do something with the container.
}
Note: I cannot use C++11 in this project.
You could use smart pointer in STL container:
Foo* MakeFoo(FooType type)
{
switch(type)
{
case FooTypeOne :
return new FooOne();
break;
case FooTypeTwo :
return new FooTwo();
break;
default:
break;
}
return null;
}
void someFunction(FooType type)
{
std::vector<std::shared_ptr<Foo> > container;
std::shared_ptr<Foo> f_ptr(MakeFoo(type));
container.push_back(f_ptr);
// Do something with the container.
for(std::vector<std::shared_ptr<Foo> >::iterator iter = container.begin();
iter != container.end(); iter++)
{
(*iter)->bar(); // call derived object's bar function respectively
}
}
As you are using C++03, shared_ptr is available under std::tr1
Note:
You need to add virtual destructor to Foo
class Foo {
public:
virtual ~Foo() {}
virtual void bar() = 0;
};
Otherwise, you get undefined behavior if you delete an object of a derived type through a pointer to the base.
The only easy and clean option that I can think of is is templates. i.e if you want to avoid pointers as you say.
template <typename FooType>
void SomeFunction() {
vector<FooType> container;
// Do something with the container.
}
void SomeFunctionCaller(){
...
if(type == "FooOne")
SomeFunction<FooOne>();
else
SomeFunction<FooTwo>();
}
But it is quite different from your design and not sure if it will fit.
Edit: Ah if you are Ok with smart pointers then that is the way to go.