If my class has a pointer of some sort that can be set by the class clients, how should I deal with deletion?
Example:
class A {
};
class B {
public:
void setA(A* a) {
this->a = a;
}
private:
A* a;
};
How should be the destructor of the class B? Should it delete a? As I see, there are two way a user can set this pointer:
... // Assume B object b being created elsewhere
A aObj;
A* aPtr = new A();
b.setA(&aObj); // It is not OK to use delete, and class member will
// point to invalid memory location once aObj goes out
// of scope
b.setA(aPtr); // Using new will make the pointer available even after
// this block of code
...
So what is the right way of deleting b? Should I always perform a new in my set method?
How should be the destructor of the class B? Should it delete a?
You, the author of the class, decides of its semantics. Don't think in terms of pointers, references, and deletes. Think in terms of design: what's the relation between A and B? What does B needs a A for?
Two common types of relation are delegation and composition. Delegation would mean that client code uses the setA member to have the instance aware of some other B instance that it may use for further uses. Composition would mean that the setA member is used to initialize an internal part of the instance.
One possible implementation of delegation is using a member pointer. I'd recommend passing a reference to setA to assign to that pointer; it sidesteps the issue of checking for 0 and makes it obvious to client code that there is no ownership issue to deal with. This is compatible with polymorphic types.
One possible implementation of composition is using a A member, and passing by reference to const or by value to assign to it. Another is to use a smart pointer, especially if A is meant to be used polymorphically. Passing by smart pointer is the simplest thing to do -- but you'll have to check for 0 and/or document the cast.
No matter what you decide to use (which doesn't have to be in this list anyway), use code as a tool to achieve your purpose or design. Don't let code dictate your thoughts.
In all my example implementations you don't have to do anything special in the destructor.
You should really really not have such a class in the first place. Instead, use a resource managing container like shared_ptr or unique_ptr to hold the pointer to a dynamically allocated object.
As you can easily see, there's no way you'll manage to keep track of who's responsible for what if you randomly allocate dynamic objects all over the place. What about copying and assignment of your class? What about exceptions in the constructor? Don't do it.
I think there would normally be be 3 scenarios, see code below:
//class B doesn't own a
class B {
public:
void setA(A& a) {
m_a = a;
}
private:
A& m_a; //Only a reference , so need to worry about delete
};
//class B owns A
class B {
public:
void setA(std::auto_ptr<A>& a) {
m_a.reset(a.release());
}
private:
boost::scoped_ptr<A> m_a; //m_a got deleted when instance of B lifetime end
};
//class B shared A with someone else
class B {
public:
void setA(boost::shared_ptr<A>& a) {
m_a = a;
}
private:
boost::shared_ptr<A> m_a; //m_a got deleted when no one need this pointer anymore(reference counting reduced to 0)
};
You have a design decision to make. Who should own the object?
The B object owns the A object, and setA passes ownership to B. B's destructor should delete the A.
Some outer code owns the A object. B will not delete it, but will depend on that outer code to destroy it at the proper time.
A smart pointer tracks the references to the A object and deletes it automatically when all references are destroyed.
The third option with the smart pointer is the simplest and most reliable, but all 3 choices can be made to work. The trick is to pick one and be deliberate about it.
During your design analysis you will have to answer the following questions:
Does object A depends on the lifetime of object B, if yes then use "composition" in which case object B will create A and is responsible for deleting it before object B itself is destroyed.
If object A is independent of the lifetime of object B then use "aggregation". You supply object A to B via B's constructor or a set method. Object B does not have to worry about destroying object A but you will have to be certain that during the lifetime of B that A is in a valid state.
If A depends on object B's lifetime but you need to create A before B, then do "dependency injection". It's like aggregation in that you can pass A to B in the constructor or set method, but A is exclusively used by B in this case and no other object is using A. B deletes A before its own destruction.
From the looks of this, you are trying to create a reference to your A object within your B class.
To clean up B properly, you would have to check if A is null first. Something like...
~B()
{
if (A)
{
delete A;
A = 0;
}
}
Keep in mind this also deletes the A object outside of the class, because they're referencing the same memory. So in a case like this, you could VERY easily reference a pointer to invalid memory if you deleted the A object.
I would not use this with a local variable either btw, as you'll lose the address of it when it goes out of scope. However, a local pointer on the other hand..well, then you won't have to worry about referencing invalid memory once you've left the scope of where A was created.
Related
I'm new to C++, and I want to know, does a pointer gets automatically deleted when the class gets deleted / destroyed? Here is an example:
class A
{
public:
Object* b;
};
Will b get `deleted when the class is deleted?
The object that the pointer points to will not be deleted. That is why it is a bad idea to use a raw pointer to refer to an object created with dynamic storage duration (i.e. via new) like this if the class object is intended to be responsible for destroying that object. Instead use std::unique_ptr:
#include<memory>
//...
class A
{
public:
std::unique_ptr<Object> b;
};
And instead of new Object(/*args*/) use std::make_unique<Object>(/*args*/) to create the object and a smart pointer to the object to store to b.
Or, most likely, there is no reason to use a pointer indirection at all. You can have a Object directly in the class. (This only really doesn't work if Object is meant to be polymorphic.)
The memory reserved for the pointer itself is freed, so in that sense, b is 'deleted'. However, if b is not set to nullptr (any any object that b points appropriately dealt with) before b is deleted, then you will likely have a memory leak.
To sum up: the pointer itself will be deleted when the object is destroyed, but nothing will happen to the object that the pointer is pointing to. You will want to create an appropriate destructor to handle this.
No, for the simple reason that nothing says that the pointer was used to allocate data: there is no implicit new in the constructor, and maybe the pointer is not used for dynamic allocation at all but for other purposes.
An extra reason is that in your use case it could be undesirable to delete the pointed data, which might be shared elsewhere for instance.
struct A
{
A(int a);
};
struct B
{
B();
void b(std::shared_ptr<A> a);
};
int main()
{
A a(1);
B b;
b.b(&a);
}
So I got this error, sorry guys it's my frist time with the smart pointers!!
Error:
no suitable constructor exists to convert from "A *" to "std::tr1::shared_ptr<A>"
How do I fix this problem!?
The entire point of a smart pointer is to have ownership. That is, it's responsible for the deallocation of whatever it's pointing it. It simply doesn't make sense to try to tell it to manage something that's already being managed by a completely different system.
In your case, a is already being automatically managed, why would you want to also be managed by a smart pointer? Even if that worked, you'd just be setting yourself for deleting it twice, which is UB.
Either give it something to own, like new A(1), or change b to operate on something it doesn't own.
Others already ranted on the design error of your code, but not the real problem why the code doesn't even compile. shared_ptr has a constructor that accepts a raw pointer, but it is marked as explicit, which means you have to explicitly write out that you want to construct a shared_ptr instance. What your function call tries, is to do that construction implicitly, which isn't allowed because of the explicit keyword.
The following will compile but give undefined behaviour because the shared_ptr will (try to) delete an object which resides on the stack and is as such not deleteable:
b.b(shared_ptr<A>(&a)); // explicit construction
A special trait of shared_ptr is that you can pass the constructor a deleter, which will be called when the owned pointer should be deleted. You can just write and use a "noop" deleter, which does just nothing; the following will not invoke undefined behaviour and will not try to delete the stack variable:
// outside of main
void noop_deleter(A*){/*do nothing*/}
// call...
b.b(shared_ptr<A>(&a, noop_deleter));
And there actually is a use for this, if you have a library API that absolutely wants a shared_ptr but you want to call it with a stack variable. The design of that API is another thing though...
std::tr1::shared_ptr has one constructor that allows to pass down a given raw pointer. So if you had a pointer to A, you would do something like:
std::shared_ptr (pMyA)
but in your case, your pointer to A points to an automatic variable NOT to a dynamically allocated memory resource that can be deleted after usage.
Something like this would be a better use case:
class B
{
void b (shared_ptr <A> pA) {}
}
int main ()
{
shared_ptr<A> pA (new A);
B b;
b.b (pA);
...
}
If I create a class MyClass and it has some private member say MyOtherClass, is it better to make MyOtherClass a pointer or not? What does it mean also to have it as not a pointer in terms of where it is stored in memory? Will the object be created when the class is created?
I noticed that the examples in QT usually declare class members as pointers when they are classes.
If I create a class MyClass and it has some private member say MyOtherClass, is it better to make MyOtherClass a pointer or not?
you should generally declare it as a value in your class. it will be local, there will be less chance for errors, fewer allocations -- ultimately fewer things that could go wrong, and the compiler can always know it is there at a specified offset so... it helps optimization and binary reduction at a few levels. there will be a few cases where you know you'll have to deal with pointer (i.e. polymorphic, shared, requires reallocation), it is typically best to use a pointer only when necessary - especially when it is private/encapsulated.
What does it mean also to have it as not a pointer in terms of where it is stored in memory?
its address will be close to (or equal to) this -- gcc (for example) has some advanced options to dump class data (sizes, vtables, offsets)
Will the object be created when the class is created?
yes - the size of MyClass will grow by sizeof(MyOtherClass), or more if the compiler realigns it (e.g. to its natural alignment)
Where is your member stored in memory?
Take a look at this example:
struct Foo { int m; };
struct A {
Foo foo;
};
struct B {
Foo *foo;
B() : foo(new Foo()) { } // ctor: allocate Foo on heap
~B() { delete foo; } // dtor: Don't forget this!
};
void bar() {
A a_stack; // a_stack is on stack
// a_stack.foo is on stack too
A* a_heap = new A(); // a_heap is on stack (it's a pointer)
// *a_heap (the pointee) is on heap
// a_heap->foo is on heap
B b_stack; // b_stack is on stack
// b_stack.foo is on stack
// *b_stack.foo is on heap
B* b_heap = new B(); // b_heap is on stack
// *b_heap is on heap
// b_heap->foo is on heap
// *(b_heap->foo is on heap
delete a_heap;
delete b_heap;
// B::~B() will delete b_heap->foo!
}
We define two classes A and B. A stores a public member foo of type Foo. B has a member foo of type pointer to Foo.
What's the situation for A:
If you create a variable a_stack of type A on the stack, then the object (obviously) and its members are on the stack too.
If you create a pointer to A like a_heap in the above example, just the pointer variable is on the stack; everything else (the object and it's members) are on the heap.
What does the situation look like in case of B:
you create B on the stack: then both the object and its member foo are on the stack, but the object that foo points to (the pointee) is on the heap. In short: b_stack.foo (the pointer) is on the stack, but *b_stack.foo the (pointee) is on the heap.
you create a pointer to B named b_heap: b_heap (the pointer) is on the stack, *b_heap (the pointee) is on the heap, as well as the member b_heap->foo and *b_heap->foo.
Will the object be automagically created?
In case of A: Yes, foo will automatically be created by calling the implicit default constructor of Foo. This will create an integer but will not intitialize it (it will have a random number)!
In case of B: If you omit our ctor and dtor then foo (the pointer) will also be created and initialized with a random number which means that it will point to a random location on the heap. But note, that the pointer exists! Note also, that the implicit default constructor won't allocate something for foo for you, you have to do this explicitly. That's why you usually need an explicit constructor and a accompanying destructor to allocate and delete the pointee of your member pointer. Don't forget about copy semantics: what happens to the pointee if your copy the object (via copy construction or assignment)?
What's the point of all of this?
There are several use cases of using a pointer to a member:
To point to an object you don't own. Let's say your class needs access to a huge data structure that is very costly to copy. Then you could just save a pointer to this data structure. Be aware that in this case creation and deletion of the data structure is out of the scope of your class. Someone other has to take care.
Increasing compilation time, since in your header file the pointee does not have to be defined.
A bit more advanced; When your class has a pointer to another class that stores all private members, the "Pimpl idiom": http://c2.com/cgi/wiki?PimplIdiom, take also a look at Sutter, H. (2000): Exceptional C++, p. 99--119
And some others, look at the other answers
Advice
Take extra care if your members are pointers and you own them. You have to write proper constructors, destructors and think about copy constructors and assignment operators. What happens to the pointee if you copy the object? Usually you will have to copy construct the pointee as well!
In C++, pointers are objects in their own right. They're not really tied to whatever they point to, and there's no special interaction between a pointer and its pointee (is that a word?)
If you create a pointer, you create a pointer and nothing else. You don't create the object that it might or might not point to. And when a pointer goes out of scope, the pointed-to object is unaffected. A pointer doesn't in any way affect the lifetime of whatever it points to.
So in general, you should not use pointers by default. If your class contains another object, that other object shouldn't be a pointer.
However, if your class knows about another object, then a pointer might be a good way to represent it (since multiple instances of your class can then point to the same instance, without taking ownership of it, and without controlling its lifetime)
The common wisdom in C++ is to avoid the use of (bare) pointers as much as possible. Especially bare pointers that point to dynamically allocated memory.
The reason is because pointers make it more difficult to write robust classes, especially when you also have to consider the possibility of exceptions being thrown.
I follow the following rule: if the member object lives and dies with the encapsulating object, do not use pointers. You will need a pointer if the member object has to outlive the encapsulating object for some reason. Depends on the task at hand.
Usually you use a pointer if the member object is given to you and not created by you. Then you usually don't have to destroy it either.
This question could be deliberated endlessly, but the basics are:
If MyOtherClass is not a pointer:
The creation and destruction of MyOtherClass is automatic, which can reduce bugs.
The memory used by MyOtherClass is local to the MyClassInstance, which could improve performance.
If MyOtherClass is a pointer:
The creation and destruction of MyOtherClass is your responsibility
MyOtherClass may be NULL, which could have meaning in your context and could save memory
Two instances of MyClass could share the same MyOtherClass
Some advantages of pointer member:
The child (MyOtherClass) object can have different lifetime than its parent (MyClass).
The object can possibly be shared between several MyClass (or other) objects.
When compiling the header file for MyClass, the compiler doesn't necessarily have to know the definition of MyOtherClass. You don't have to include its header, thus decreasing compile times.
Makes MyClass size smaller. This can be important for performance if your code does a lot of copying of MyClass objects. You can just copy the MyOtherClass pointer and implement some kind of reference counting system.
Advantages of having the member as an object:
You don't have to explicitely write code to create and destroy the object. It's easier and and less error-prone.
Makes memory management more efficient because only one block of memory needs to be allocated instead of two.
Implementing assignment operators, copy/move constructors etc is much simpler.
More intuitive
If you make the MyOtherClass object as member of your MyClass:
size of MyClass = size of MyClass + size of MyOtherClass
If you make the MyOtherClass object as pointer member of your MyClass:
size of MyClass = size of MyClass + size of any pointer on your system
You might want to keep MyOtherClass as a pointer member because it gives you the flexibility to point it to any other class that is derived from it. Basically helps you implement dynamice polymorphism.
It depends... :-)
If you use pointers to say a class A, you have to create the object of type A e.g. in the constructor of your class
m_pA = new A();
Moreover, don't forget to destroy the object in the destructor or you have a memory leak:
delete m_pA;
m_pA = NULL;
Instead, having an object of type A aggregated in your class is easier, you can't forget to destroy it, because this is done automatically at the end of lifetime of your object.
On the other hand, having a pointer has the following advantages:
If your object is allocated on the
stack and type A uses a lot of memory
this won't be allocated from the
stack but from the heap.
You can construct your A object later (e.g. in a method Create) or destroy it earlier (in method Close)
An advantage of the parent class maintaining the relation to a member object as a (std::auto_ptr) pointer to the member object is that you can forward declare the object rather than having to include the object's header file.
This decouples the classes at build time allowing to modify the member object's header class without causing all the clients of your parent class to be recompiled as well even though they probably do not access the member object's functions.
When you use an auto_ptr, you only need to take care of construction, which you could typically do in the initializer list. Destruction along with the parent object is guaranteed by the auto_ptr.
The simple thing to do is to declare your members as objects. This way, you do not have to care about copy construction, destruction and assignment. This is all taken care of automatically.
However, there are still some cases when you want pointers. After all, managed languages (like C# or Java) actually hold member objects by pointers.
The most obvious case is when the object to be kept is polymorphic. In Qt, as you pointed out, most objects belong to a huge hierarchy of polymorphic classes, and holding them by pointers is mandatory since you don't know at advance what size will the member object have.
Please beware of some common pitfalls in this case, especially when you deal with generic classes. Exception safety is a big concern:
struct Foo
{
Foo()
{
bar_ = new Bar();
baz_ = new Baz(); // If this line throw, bar_ is never reclaimed
// See copy constructor for a workaround
}
Foo(Foo const& x)
{
bar_ = x.bar_.clone();
try { baz_ = x.baz_.clone(); }
catch (...) { delete bar_; throw; }
}
// Copy and swap idiom is perfect for this.
// It yields exception safe operator= if the copy constructor
// is exception safe.
void swap(Foo& x) throw()
{ std::swap(bar_, x.bar_); std::swap(baz_, x.baz_); }
Foo& operator=(Foo x) { x.swap(*this); return *this; }
private:
Bar* bar_;
Baz* baz_;
};
As you see, it is quite cumbersome to have exception safe constructors in the presence of pointers. You should look at RAII and smart pointers (there are plenty of resources here and somewhere else on the web).
I have a class MyClassA. In its constructur, I am passing the pointer to instance of class B. I have some very basic questions related to this.
(1) First thing , is the following code correct? ( the code that makes a shallow copy and the code in methodA())
MyClassA::MyClassA(B *b){
this.b = b;
}
void MyClassA::methodA(){
int i;
i = b.getFooValue();
// Should I rather be using the arrow operator here??
// i = b->getFooValue()
}
(2) I am guessing I don't need to worry about deleting memory for MyClassA.b in the destructor ~MyClassA() as it is not allocated. Am I right?
thanks
Update: Thank you all for your answers! MyclassA is only interested in accessing the methods of class B. It is not taking ownership of B.
You need the arrow operator since b is a pointer.
Yes, unless the user of MyClassA expects to take the ownership of b. (You can't even be sure if b is a stack variable where delete-ing it will may the code crash.)
Why don't you use a smart pointer, or even simpler, a reference?
First thing , is the following code
correct? ( the code that makes a
shallow copy and the code in
methodA())
The answer depends upon who owns the responsibility of the B object's memory. If MyClassA is supposed just to store the pointer of A without holding the responsibility to delete it then it is fine. Otherwise, you need to do the deep copy.
I am guessing I don't need to worry
about deleting memory for MyClassA.b
in the destructor ~MyClassA() as it is
not allocated. Am I right?
Again depends on how memory for B is allocated. Is it allocated on stack or heap? If from stack then you need not explicitly free it in destructor of MyClassA, otherwise you need to to delete it.
1) . It depends on the life time of the pointer to B.
Make sure the when you call b->getFooValue(); b should be a valid pointer.
I will suggest use of initilization list and if you are only reading the value of the B object though it pointer then make it pointer to constant data.
MyClassA::MyClassA(const B *bObj) : b(bObj)
{}
2). As long as B is on the stack on need to delete it and if it is allocated to heap then it must be deleted by it the owner else you will have memory leak.
You can use smart pointer to get rid of the problem.
MyClassA::MyClassA(B *b){
this.b = b;
}
should be:
MyClassA::MyClassA(B *b){
this->b = b;
}
because this is treated as a pointer.
1)
this.b = b;
Here you pass a pointer to an instance of B. As Mac notes, this should be:
this->b = b;
b.getFooValue();
This should be b->getFooValue(), because MyClassA::b is a pointer to B.
2) This depends of how you define what MyClassA::b is. If you specify (in code comments) that MyClassA takes over ownership over the B instance passed in MyClassA's constructor, then you'll need to delete b in MyClassA's destructor. If you specify that it only keeps a reference to b, without taking over the ownership, then you don't have to.
PS. Regrettably, in your example there is no way to make ownership explicit other than in code documentation.
What is the best approach to encapsulate objects and manage their lifetime? Example: I have a class A, that contains an object of type B and is solely responsible for it.
Solution 1, clone b object to ensure that only A is able to clean it up.
class A
{
B *b;
public:
A(B &b)
{
this->b = b.clone();
}
~A()
{
delete b; // safe
}
};
Solution 2, directly use the passed object, we risk a potential double free here.
class A
{
B *b;
public:
A(B *b)
{
this->b = b;
}
~A()
{
delete b; // unsafe
}
};
In my actual case, solution #2 would fit best. However I wonder if this is considered bad code because someone might not know about the behavior of A, even if it's documented. I can think of these scenarios:
B *myB = new B();
A *myA = new A(myB);
delete myB; // myA contains a wild pointer now
Or,
B *myB = new B();
A *firstA = new A(myB);
A *secondA = new A(myB); // bug! double assignment
delete firstA; // deletes myB, secondA contains a wild pointer now
delete secondA; // deletes myB again, double free
Can I just ignore these issues if I properly document the behavior of A? Is it enough to declare the responsibility and leave it up to the others to read the docs? How is this managed in your codebase?
I never delete anything myself unless I really have to. That leads to errors.
Smart pointers are your friend. std::auto_ptr<> is your friend when one object owns another and is responsible for deleting it when going out of scope. boost::shared_ptr<> (or, now, std::tr1::shared_ptr<>) is your friend when there's potentially more than one object attached to another object, and you want the object deleted when there's no more references to it.
So, either use your solution 1 with auto_ptr, or your solution 2 with shared_ptr.
You should define your object so that the ownership semantics are, as much as possible, defined by the interface. As David Thornley pointed out, std::auto_ptr is the smart pointer of choice to indicate transfer of ownership. Define your class like so:
class A
{
std::auto_ptr<B> b;
public:
A(std::auto_ptr<B> b)
{
this->b = b;
}
// Don't need to define this for this scenario
//~A()
//{
// delete b; // safe
//}
};
Since the contract of std::auto_ptr is that assignment = transfer of ownership, your constructor now states implicitly that an A object has ownership of the pointer to B it's passed. In fact, if a client tries to do something with a std::auto_ptr<B> that they used to construct an A after the construction, the operation will fail, as the pointer they hold will be invalid.
If you are writing code that someone else will be using later, these issues must be addressed. In this case I would go for simple reference counting (maybe with smart pointers). Consider the following example:
When an instance of the encapsulating class is assigned an object B, it calls a method to increase object's B reference counter. When the encapsulating class is destroyed, it doesn't delete B, but instead calls a method do decrease reference count. When the counter reaches zero, object B is destroyed (or destroys itself for that matter). This way multiple instances of encapsulating class can work with a single instance of object B.
More on the subject: Reference Counting.
If your object is solely responsible for the passed object then deleting it should be safe. If it is not safe than the assertion that you are solely responsible is false. So which is it? If you're interface is documented that you WILL delete the inbound object, then it is the caller responsibility to make sure you receive an object that must be deleted by you.
If you're cloning A, and both A1 and A2 retain references to B, then B's lifetime is not being controlled entirely by A. It's being shared among the various A. Cloning B ensures a one-to-one relationship between As and Bs, which will be easy to ensure lifetime consistency.
If cloning B is not an option, then you need to discard the concept that A is responsible for B's lifetime. Either another object will need to manage the various B, or you'll need to implement a method like reference counting.
For reference, when I think of the term 'Clone', it implies a deep copy, which would clone B as well. I'd expect the two As to be completely detached from each other after a clone.
I don't clone things unnecessarily or "just to be safe".
Instead I know whose responsibility it is to delete something: either via documentation, or by smart pointers ... for example, if I have a create function which instantiates something and returns a pointer to it and doesn't delete it, so that it's unclear where and by whome that thing is ever supposed to be deleted, then instead of create's returning a naked pointer I might define create's return type as returning the pointer contained within some kind of smart pointer.