I was wondering whether using a reference of some interface instead of pointer could result in some complications that I am overlooking. The reason why I want to do this is to make clear which objects should 'delete' pointers given to them on construction and which ones should just use it and not worry about other objects lifetimes to allow for multiple instances to share one object. (shared_ptr is not an option)
Here is an example:
class Parent
{
public:
virtual void WhoAmI() { printf("Parent\n"); }
};
class Child : public Parent
{
public:
void WhoAmI() { printf("Child\n"); }
};
class ParentUser
{
public:
ParentUser(Parent& parent) : _parent(parent) {}
public:
Parent& _parent;
};
class ParentOwner
{
public:
ParentOwner(Parent* pParent): _pParent(pParent), _parentUser(*pParent) {}
~ParentOwner() { delete _pParent; }
public:
Parent* _pParent;
ParentUser _parentUser;
};
int main ()
{
Parent* pParent = new Child();
ParentOwner parentOwner(pParent);
parentOwner._parentUser._parent.WhoAmI();
char stopper;
cin >> stopper;
return 0;
}
This worked correctly and the output was the expected: 'Child'
Your use of a reference to indicate use of an object and a pointer to indicate ownership is perfectly fine. You’ve simply defined your own convention for ownership, and everything should work as long as all your code follows that convention. Note that you can only have one object in your system that has a pointer to the object to be deleted.
In your example, the Child object can be passed as a constructor argument to only one ParentOwner object.
In general the object that allocated the memory should be reponsible for freeing it.
Deleting it in other objects can lead to trouble.
Imagine this scenario:
Object A creates "Obj".
Object A passes it on to object B
Object B deletes it.
Object A who doesn't know "Obj" was deleted passes it now to object C.
Object C tries to use "Obj". BOOM!
Related
I am trying to create and use a std::shared_ptr within a class function whose constructor takes in a std::shared_ptr private data member (of the same class) and another std::shared_ptr created with a raw pointer to the class object (this).
Whenever I call the function that creates the std::shared_ptr (foo), I get a _CrtIsValidHeapPointer(block) assertion. I'm assuming it has something to do with the way in which the shared_ptr is being deleted, but I can't seem to figure it out, and I've searched all over the Internet. Maybe I'm not fully understanding how shared_ptrs work.
Is it not acceptable to create a shared_ptr using the this pointer, or a pre-existing shared_ptr data member?
class Containing_Class;
class Some_Class
{
};
class Set_Value_Command
{
public:
Set_Value_Command(std::shared_ptr<Some_Class> ptr1, std::shared_ptr<Containing_Class> ptr2)
: _ptr1(ptr1), _ptr2(ptr2)
{}
private:
std::shared_ptr<Some_Class> _ptr1;
std::shared_ptr<Containing_Class> _ptr2;
};
class Containing_Class
{
public:
Containing_Class(std::shared_ptr<Some_Class> psc)
: _psc(psc)
{}
void foo()
{
std::shared_ptr<Set_Value_Command> command = std::make_shared<Set_Value_Command>(_psc, std::shared_ptr<Containing_Class>(this));
}
private:
std::shared_ptr<Some_Class> _psc;
};
Here is the main() function. When foo() is called, the assertion happens:
int main()
{
std::shared_ptr<Some_Class> some_class = std::make_shared<Some_Class>();
Containing_Class cc(some_class);
cc.foo();
}
Is it not acceptable to create a shared_ptr using the this pointer
Not by itself, no. And doing so in your example is very bad. Your Containing_Class object is being created in automatic memory of main()'s local stack frame, and thus will be destroyed automatically when it goes out of scope when main() exits. But creating a shared_ptr from this inside of the Containing_Class object will assign ownership of this to the shared_ptr, which will then try to delete this when there are no more shared_ptr references to this. delete'ing an object that was not created with new to begin with is undefined behavior, and is why you are crashing with an error about an invalid heap pointer.
In order to allow shared_ptr to refer to this, Containing_Class would need to derive from std::enable_shared_from_this, and this would have to point at an object that is created dynamically and owned by a shared_ptr. Only then can Containing_Class call its inherited shared_from_this() method to get a shared_ptr to itself.
For example:
class Containing_Class;
class Some_Class
{
};
class Set_Value_Command
{
public:
Set_Value_Command(std::shared_ptr<Some_Class> ptr1, std::shared_ptr<Containing_Class> ptr2)
: _ptr1(ptr1), _ptr2(ptr2)
{}
private:
std::shared_ptr<Some_Class> _ptr1;
std::shared_ptr<Containing_Class> _ptr2;
};
class Containing_Class : public std::enable_shared_from_this<Containing_Class>
{
public:
Containing_Class(std::shared_ptr<Some_Class> psc)
: _psc(psc)
{}
void foo()
{
std::shared_ptr<Set_Value_Command> command = std::make_shared<Set_Value_Command>(_psc, shared_from_this());
}
private:
std::shared_ptr<Some_Class> _psc;
};
int main()
{
auto some_class = std::make_shared<Some_Class>();
auto cc = std::make_shared<Containing_Class>(some_class);
cc->foo();
}
With the code
std::shared_ptr<Containing_Class>(this)
you introduce a second *this owner, i.e. command is the owner of a shared pointer that controls cc life. That is the first issue. Yet another, following issue is that command is pointing to a stack object.
Usually *this is owned by someone and passing ownership to another owner never works.
The current code is impossible to fix due to lack of the code aim.
I've stared using smart pointer and trying to wrap my head around best uses for it. I've read plenty of articles but I'm confused on which to use in the following example. I've included a shared_ptr and unique_ptrexamples to show what I'm trying to accomplish:
class A
public:
A();
private:
unique_ptr<B> ptrB;
unique_ptr<SomeObject> ptrUnique;
shared_ptr<SomeObject> ptrShared;
A::A()
{
ptrB(new B());
ptrUnique(new SomeObject());
ptrB->PassUnique(ptrUnique);
ptrShared(new SomeObject());
ptrB->PassShared(ptrShared);
}
class B:
public:
void PassUnique(unique_ptr<SomeObject> &ptr_unique);
void PassShared(weak_ptr<SomeObject> &ptr_weak);
void DoSomething();
private:
unique_ptr<SomeObject> ptrUnique;
weak_ptr<SomeObject> ptrWeak;
B::PassUnique(unique_ptr<SomeObject> &ptr_unique)
{
ptrUnique = ptr_unique;
}
B::PassShared(weak_ptr<SomeObject> &ptr_weak)
{
ptrWeak = ptr_weak;
}
B::DoSomething()
{
ptrUnique->SomeMethod();
shared_ptr<SomeObject> ptr1 = ptrWeak.lock();
ptr1->SomeMethod();
}
SomeObject class can be any class. A good example is a database handle that I pass from the parent class A were it was originally initiated to multiple class like B. And from B to C if it exists. My question is if I'm passing a unique_ptr as a reference will setting for example ptrUnqiue = ptr_unique in B:PassUnique create a copy which then is not correct? Or should this be done via shared_ptr? This understanding is what is confusing with smart pointers for me and would appreciate clarification.
Well, this is a question of lifetime. Do you need SomeObject to outlive A? Do B send or is being use outside of this context? You have to decide when your objects dies. If you think SomeObject exists only in this context, I would recommend A to be the owner, as it allocate the resource, and be to old a raw pointer to SomeObject. I would look like this:
class A
public:
A();
private:
unique_ptr<B> ptrB;
unique_ptr<SomeObject> ptrUnique;
};
A::A()
{
ptrB(new B());
ptrUnique(new SomeObject());
ptrB->PassUnique(*ptrUnique);
}
class B:
pubic:
void PassUnique(SomeObject& obj);
void DoSomething();
private:
SomeObject* ptrUnique;
};
B::PassUnique(SomeObject& obj)
{
ptrUnique = &obj;
}
B::DoSomething()
{
ptrUnique->SomeMethod();
}
There is no such thing as
ptrUnique = ptr_unique;
If you need SomeObject to be used and owned outside of this structure, then go with std::shared_ptr like you did. There were no errors with your std::shared_ptr code.
Answer is basically what would be a lifetime of the pointer in the A, B and/or C. Think of it as ranges, [A...a), [B...b) and [C...c). If [B...b) is always within [A...a) and [C...c) is always within [B...b), they have like a Russian dolls hierarchy, then passing down ref-to-ptr is ok. If ranges overlap and changes wildly so you don't really control where last ptr will be destructed and object will be deleted, you'd have to go with shared_ptr.
According to definition : When an object of this class is copied, the pointer member is copied, but not the pointed buffer, resulting in two objects pointing to the same so we use copy constructor. But in following class there is no copy constructor but it Works! why? Why i dont need to deep copying?
class Human
{
private:
int* aValue;
public:
Human(int* param)
{
aValue=param;
}
void ShowInfos()
{
cout<<"Human's info:"<<*aValue<<endl;
}
};
void JustAFunction(Human m)
{
m.ShowInfos();
}
int main()
{
int age = 10;
Human aHuman(&age);
aHuman.ShowInfos();
JustAFunction(aHuman);
return 0;
}
output:
Human's info : 10
Human's info : 10
A copy constructor is useful when your class owns resources. In your case, it doesn't - it neither creates nor deletes aValue itself.
If you did do that though, say:
Human()
{
aValue=new int;
}
and properly cleaned up the memory:
~Human()
{
delete aValue;
}
then you'd run into issues, because Human a; and Human b(a); would have the members aValue point to the same location, and the when they go out of scope, the same memory is released, resulting in a double delete.
As has already been mentioned, the reason it works for you is that it's actually fine to have multiple pointers pointing to the same object - that's kind of the point, share data without copying it.
the issues arrive if the object pointed to has it's lifetime managed by the wrapping class, ie: it is created and destroyed within methods implemented by the class - typically the class's constructor and destructor. In that case a deep copy would be necessary in the copy constructor.
In your (admittedly contrived) example where the int has a longer lifetime that the object carrying the pointer you should examine using a reference as a member, initialised in an initialiser list. This removes the possibility of forgetting yourself and deleting the object from within the class.
class Human
{
private:
int& aRef;
public:
Human(int& param)
: aRef(param)
{
}
};
You should also consider whether the pointer or reference should be to a const object:
class Human
{
private:
const int& aRef;
public:
Human(const int& param)
: aRef(param)
{
}
};
This works because the pointer in the class points to the stack variable age.
You haven't written a destructor for your class Human, so doesn't try to do a double delete when the Human is copied in JustAFunction
If you used it differently, for example sending a newed int into the class you would have a memory leak instead.
Human human(new int);
If you copy that, you have two pointers pointing to the same memory, which in itself isn't a problem, but makes it hard to decide who is in charge of releasing that memory.
I am using a boost::ptr_vector, but I believe this applies to a standard std::vector as well. I am trying to place pointers to objects polymophically into a boost::ptr_vector the hierarchy is that I have an Entity that inherits from Object being created with the line
Object * newObject = new Entity(param1, param2); // then I attempt to add it to the ptr_vector
but if I break the program (Visual Studio 2010) to look at what is being held the pointer is never redirected from garbage, and garbage is being held. I step through the code, and it does enter the parameterized constructor, and follows the correct logical steps with it.
I am uncertain what is going wrong. do I need to have specific member functions in the parent, or the child in order for this polymorphic behavior to work (currently all children have parameterized constructors unique to their type, and destructors along with polymorphic interaction methods). must I have assignment operators, or should I have a constructor in the Object class.
It seems to be that the call to operator new is not resolving to an object, but resolving to something else, but VS2010 is not throwing an error.
Edit: explanation of what should be happening.
stepping through a 2D std::vector(rectangular/non-jagged)
using case/switch to determine object to be generated, and added to structure
pointer to Object is created, and assigned to new // I think this is where the problem is happening
then the reference of that pointer is pushed onto a manager-member boost::ptr_vector
in Visual Studio 2010 I put a break at the line to create the pointer, and assign new (polymorphic), and one on the line for the push_back() to the boost::ptr_vector watching the pointer. The temp pointer value is created, and stepping into the constructor it follows all logical steps for that constructor, and when the constructor finishes, and the stack returns to the line that called the constructor the pointer is still the same value (I think this is acceptable), but when I look at the object that it points to all the values show up as question marks (including the statically composed member objects). then when the push back triggers, and enters boost-header the x value show the same information.
it almost seems like the pointer is being made, and the datams of the object are created, but once the constructor is finished it doesn't actually assign the values to the parent class object which should be considerably simple with regards to polymophic behavior.
example headers of concern (the real headers do have member variables, and their implementations are in a separate cpp file):
class Object{
public :
virtual void interact(int action, Object& source){}
virtual void updateObject(float duration){}
virtual ~Object(){}
bool operator==(const Object& _other)const;
bool operator!=(const Object& _other)const;
};
class Entity : public Object{
public:
Entity(Vector3 location, Type thisType, SpecialType difficulty=noSpecial);
~Entity();
void interact(int action, Object& source);
void updateObject(float duration);
};
Edit: changing context to better target problem at hand, and receive a solution
The pointer value only changes after the constructor has finished, it's not a problem. It's logical because first a temporary pointer is acted upon and only the it is assigned to your pointer.
After
Object * newObject = new Entity(param1, param2);
you will have newObject pointing to the freshly created object. While the constructor is
running, newObject is still not assigned. If you have afterwards e.g.
vec.push_back(newObject);
you can step into the push_back method and see the argument is an Object having
a virtual table referencing to Entity methods. (You have a virtual destructor at least,
right?)
Based on what you've posted, it's difficult (if even possible) to be sure of the problem, not to mention how it's coming about/how to fix it.
Perhaps it's better to start from something that actually works, and add the functionality you need, or at least get some idea of places you're deviating from what's expected/what works. So, here's a small sample of creating objects dynamically, putting them into a ptr_vector, using a virtual function in each to verify that what's in the container is what's expected, and then letting the container go out of scope (and in the process, destroying the objects referred to by the pointers it contains).
#include "boost/ptr_container/ptr_vector.hpp"
#include <iostream>
#include <string>
#include <sstream>
class Object {
std::string name;
public:
Object(std::string const &n) : name(n) {}
virtual std::ostream &write(std::ostream &os) const {
return os << name;
}
virtual ~Object() { std::cout << "Object being destroyed\n"; }
};
class Entity : public Object {
int value;
public:
Entity(int v, std::string name) : Object(name), value(v) {}
std::ostream &write(std::ostream &os) const {
return os << "Entity: " << value;
}
~Entity() { std::cout << "Entity being destroyed\n"; }
};
int main() {
boost::ptr_vector<Object> objects;
for (int i=0; i<10; i++) {
std::stringstream name;
name << "object: " << i;
if (i & 1)
objects.push_back(new Object(name.str()));
else
objects.push_back(new Entity(i, name.str()));
}
boost::ptr_vector<Object>::iterator pos;
for (pos = objects.begin(); pos != objects.end(); pos++) {
pos->write(std::cout);
std::cout << "\n";
}
return 0;
}
At least for me, the output looks like this:
Entity: 0
object: 1
Entity: 2
object: 3
Entity: 4
object: 5
Entity: 6
object: 7
Entity: 8
object: 9
Entity being destroyed
Object being destroyed
Object being destroyed
Entity being destroyed
Object being destroyed
Object being destroyed
Entity being destroyed
Object being destroyed
Object being destroyed
Entity being destroyed
Object being destroyed
Object being destroyed
Entity being destroyed
Object being destroyed
Object being destroyed
For what it's worth, note the destructors -- when an Object is destroyed, only the base dtor is invoked, but when an Entity is destroyed, first the derived dtor is invoked, then the base dtor is invoked (so we see both 'Entity being destroyed' and 'Object being destroyed").
A question about boost::shared_ptr here:
I have 3 Classes.
A is some kind of Main class which is responsible to manage everything.
B is a class which just has functions to do some work.
Dispatcher is just a class which wraps around a seperate thread, which gets the work from Instaces of Bdone in this thread.
So it is kinda working like this: A has an instance of Dispatcher. Now on occassion A generates an instance of B and passes it to the dispatcher.
The important part is, that B needs to call A::callback() when it's done. This is why B gets a reference to A in it's constructor ( see code below )
A.hpp
class A : public boost::enable_shared_from_this<A>
{
public:
A();
void sendB();
void callback();
private:
Dispatcher m_Dispatcher;
};
B.hpp
class B
{
public:
B(boost::shared_ptr<A> ptr);
boost::shared_ptr<A> m_PointerToA;
/* Some other functions */
};
Dispatcher.hpp
class Dispatcher
{
public:
void run();
void dispatch(boost::shared_ptr<B> b);
private:
void doWork();
boost::thread m_Thread;
};
A.cpp
A::A()
{
m_Dispatcher.run();
}
void A::sendB()
{
boost::shared_ptr ptr_B;
ptr_B.reset(new B(this->shared_from_this);
m_Dispatcher.dispatch(ptr_B);
}
B.cpp
B::B(boost::shared_ptr<A> ptr) :
: m_PointerToA(ptr)
{
}
main_example.cpp
int main()
{
A instanceA;
while(true)
{
instanceA.sendB();
/* Do some other stuff */
}
return 0;
}
So my question is:
Is it reasonable to use boost::shared_ptr for this purpose?
I am not sure if the shared_ptr is the right thing to go here. My problem is, that I don't know what happens exactly when I call the constructor from B and pass it the this pointer. Now according to shared_ptr I would assume that m_PointerToA takes ownership of A. But this would mean that when the work in the Dispatcher is done and my instance of B gets deleted it would also delete the reference to m_PointerToA which would actually mean it kills the object itself despite the fact there is an actual instance of A in the main loop.
Update:
Added some code and updated question itself to make it more clear.
There's nothing particular wrong with this design. However I would prefer to instead use boost::function<> & boost::bind. It gives you way better flexibility for the callback and doesn't tie B as tightly to A. Of course you still have to be vary of the usual threading caveats.
Yes, it is okay to just copy/assign a shared_ptr, it will only increase the reference count.
In your example, shared_from_this() will create a (here: temporary) shared_ptr from the weak_ptr that is hold by this (ref count 1), so when you assign/copy-construct m_PointerToA, the reference count will increase temporarily to 2 before the ctor returns and the temporary object will be destroyed, decreasing the reference count to 1 again (the shared_ptr is "aware" of the one instance in your B object).
So, yes, if B is deleted, it will destroy A in this case (as the reference count drops to 0).
Your concern
This would mean if my Instance of B is deleted, it would also delete m_PointerToA which would also kill my instance of A . Of course my original instance of A is held elsewhere.
only shows that if you plan/need/intend to keep a pointer to the instance of A for further usage, you should do so with a shared_ptr as well instead of a raw pointer. If you have control of A's interface, the easiest way would be a named constructor like this:
class A : public boost::enable_shared_from_this<A> {
public:
static boost::shared_ptr<A> create();
void initClassB();
// ....
private:
A();
A( const A & other );
A& operator=( const A & rhs );
};
boost::shared_ptr<A> A::create() {
return boost::shared_ptr<A>( new A() );
}
Then, even if your instance of B is deleted, the instance of A will still survive because the reference count of the shared_ptr is still (at least) 1.