When in particular are smart pointers good to use, and why use a smart pointer anyway if pointers in C++ are discouraged to use? As an example:
class Object { }
smart_pointer < Object > pInstance;
//wherein I can use the very simple way
Object instance;
Smart pointers are good when you need to maintain ownership of an object. Using them will ensure proper destruction. When pointer is treated as a reference, using smart pointer can sometimes be worse (for example, in terms of performance).
Pointers are an essential part of C++, but using them got much easier as smart ones in C++11 with move semantics introduced (which essentially made unique_ptr possible). That's why in modern code you should always use std::unique_ptr or std::shared_ptr if available.
Edit: You asked for an example, where a pointer could be beneficial to use. The most common problem that I can think of is an optional component of some system. This component will use a lot of memory, so you don't want to always allocate it, neither you control its allocations (so it can't be in "empty" state itself, i.e. is not nullable). Boost.Optional and C++14-ish std::optional allocate memory of the POD-ish size of T, so they won't do. Using a pointer you can optionally allocate that memory:
class Outer {
std::unique_ptr<BigInner> optionalComponent;
public:
void initializeOptionalComponent() {
optionalComponent = new BigInner();
}
void useOptionalComponent() {
if (!optionalComponent)
// handle the error
// operate
}
};
That will solve the problem, but will introduce the obvious, another problem: optionalComponent can be null, which requires all functions using it to check for valid state at all times. Had it been a plain by-value member, it would (or at least should) be always in valid state. As such, if you don't need a pointer, don't use it at all, use vector<MyClass> and plain members.
Anyway, using smart pointer in this case allows you to keep the Rule of Zero; you don't have to write destructor, copy constructor or assignment operator, and the class will behave safely.
Quick answer : smart pointers are useful for (notably)
Enforcing RAII
Managing pointers ownership
Enforcing RAII
One problem that comes with pointers and cause (in many way, some obvious, some twisted) crashes in your program is that you are responsible for the memory underneath them. That means that when you allocate memory dynamically (through new), you are responsible for this memory, and must not forget to call delete. That means it will happen, and worse, there are case where even if you didn't forget, the delete statement will never be reached.
Consider this code :
void function(){
MyClass* var = new MyClass;
//Do something
delete var;
}
Now, if this function throw an exception before the delete statement is reached, the pointer will not be deleted... Memory leak !
RAII is a way to avoid this :
void function(){
std::shared_ptr<MyClass> var(new MyClass);
//Do something
//No need to delete anything
}
The pointer is held by an object, and deleted in its destructor. The difference with the previous code is that, if the function throw an exception, the destructor of the shared pointer will be called and the pointers will thus be deleted, avoiding a memory leak.
RAII takes advantages of the fact that when a local variable goes out of scope, its dtor is called.
Managing pointers ownership
Note which smart pointer I used in the previous example. The std::shared_ptr is a smart pointer that is useful when you pass pointers around. If many part of your code need a pointer to the same object, it can be tricky to decide where it should be deleted. You might want to delete the pointer somewhere, but what if another part of your code is using it ? It results in an access to a deleted pointer, which is not desirable at all ! std::shared_ptr helps prevent this. When you pass a shared_ptr around, it keeps track of how many part of the code have a reference to it. When there isn't any reference to the pointer anymore, this pointer deletes the memory. In other terms when nobody uses the pointer anymore, it is safely deleted.
There are other kind of smart pointers that address other issue, like std::unique_ptr which provide a pointer that is the only owner of the pointer underneath it.
Note - Small explanation on polymorphism
You need pointers to use polymorphism. If you have an abstract class MyAbstract (that means, it have at least one virtual, say doVirtual()), it cannot be instantiated. The following code :
MyAbstract var;
won't compile, you'll get something along the line of Can't instantiate abstract class from your compiler.
But this is legal (with both ImplA and ImplB inheriting publicly from MyAbstract:
MyAbstract* varA = new ImplA;
MyAbstract* varB = new ImplB;
varA->doVirtual(); //Will call ImplA implementation
varB->doVirtual(); //Will call ImplB implementation
delete varA;
delete varB;
Related
I'd like to illustrate one thing I've seen:
class Something {};
void do_something(const Something *p_sth) {}
Then:
do_something(new Something());
should cause a memory leak because when you call new you should also always call delete, right? Would this be a good solution?
void do_something(const Something *p_sth)
{
delete p_sth;
}
Or is it better to use references &? I also find out that smart pointers can solve this, so delete isn't required (it seems as a good thing but I have never used it before). I just want to know what's the best solution for this to avoid the memory leak. Thanks
*Thank you all for your answers. It helped me to clear up few things. I'm also sorry for the code I posted as it was maybe too general.
Your suggestion of assuming the ownership of the pointer and deleting the object has problems.
That behaviour is not idiomatic in c++. Programmers expect that they must delete every object that they allocate with new. If a user of your function expects that they're responsible for deleting the object whose address they pass to the function, then your solution breaks apart. Also, it prevents using your function with objects that must keep existing after the call has ended:
Something* s = new s();
do_something(s);
s.foo() // oops, object was deleted, I can't use it anymore
delete s; // oops, double delete because I'm for some reason not responsible for deleting the object that I allocated
Your solution also prevents using automatically and statically allocated objects with the function.
Something s;
do_something(&s); //oops, do_something assumes that object is dynamically allocated
All of these caveats would have to be documented to the user of the function.
A raw pointer without deleting inside the function has none of these problems. Managing the callers memory should really not be the responsibility of your function. Doing that would break the single responsibility principle. There's nothing wrong with raw pointer parameters when you don't want to transfer or share ownership. If you do want to imply changes in ownership, then use smart pointers which were designed exactly for that.
Smart pointers don't have some of the above problems, but they still prevent using the function with automatic and static objects.
A reference parameter is in many cases ideal. It communicates the caller that they're still responsible for the object. As a bonus, The lack of need for addressof operator allows slightly nicer syntax. Sure, the caller may still forget to manage their memory, but as I pointed out, that shouldn't be your responsibility.
References have one potential drawback. They can't be null. If you don't need null, then it's actually an advantage.
Which solution is ideal, depends on what you need. Following is not true for all corner cases, but should hold for most common cases:
If you want to modify the object, then pass a reference.
Unless you need null, in which case use a pointer
If you just want to read the object, then
If the object is copyable, small (size less than or equal to word), doesn't cointain pointers to dynamic objects and not polymorphic, then pass by value
Otherwise or if you don't know those things because you're writing a template, pass a const reference
Unless you need null, in which case use a pointer
If you want to If you want to transfer ownership, then use unique_ptr
If you want that ownership to be shared, then use shared_ptr
Best is to use a smart pointer
class Something {};
void do_something(std::shared_ptr<Something> p_sth)
{
...
}
That way the ownership is clear when you look at the prototype as well as you get an automatic delete when you leave scope.
I just want to know what's the best solution for this to avoid the memory leak. Thanks
The best solution to ensure there are no memory leaks would be to use std::shared_ptrwhich is a smart pointer which, as soon as it does not have any references, deletes itself. This pointer is best if you have more than on reference to the same pointer. Use std::unique_ptr if there is only one reference at a given time.
This will prevent memory leaks and I also prefer using smart pointers rather than standard pointers as they are very powerful. Also, retaining to the question:
Or is it better to use references &?
Use references wherever you need to reference the object, if you delete the reference, being a smart pointer, it will delete the pointer as well (Being there are no other references to that pointer)
I hope this answers your questions :)
Prefer to avoid the use of raw pointers.
If you do not need a heap allocation and can use a stack allocated variable, then prefer to pass by reference (or even pass by value if an appropriate move constructor is in place, but that's a topic for another day).
If you need a heap allocation (for polymorphism, dependency injection, information hiding, transfer of ownership etc.) then determine what the ownership semantics will be for that object and use the appropriate smart pointer to manage those semantics.
If all else fails and you must use a raw pointer (perhaps you are dealing with a legacy interface or a C interface, or something similar) then again, clearly define your ownership semantics and document them to make it clear who is responsible for deleting the heap allocated object, etc.
If you must have a raw pointer to a stack allocated object then document that you will not be deleting the pointer and be careful about documenting the lifetime of the pointer to avoid accessing the object after it has gone out of scope.
Cleanest solution would be to avoid the pointer completely.
And yes, a reference is a good idea.
void do_something(const Something &p_sth) {}
Then you can declare your 'something' on the Stack.
void function_that_does_something()
{
Something mySomething;
do_something( mySomething );
}
It is always best to let the compiler do the cleanup for you.
This seems like a rather trivial or at least common question, but I couldn't find a satisfying answer on google or on SO.
I'm not sure when I should implement a destructor for my class.
An obvious case is when the class wraps a connection to a file, and I want to make sure the connection is closed so I close it in the destructor.
But I want to know in general, how can I know if I should define a destructor. What guidelines are there that I can check to see if I should have a destructor in this class?
One such guideline I can think of, is if the class contains any member pointers. The default destructor would destory the pointers on deletion, but not the objects they're pointing at. So that should be the work of a user-defined destructor. E.g: (I'm a C++ newbie, so this code might not compile).
class MyContainer {
public:
MyContainer(int size) : data(new int[size]) { }
~MyContainer(){
delete [] data;
}
// .. stuff omitted
private:
int* data;
}
If I hadn't supplied that destructor, than destroying a MyContainer object would mean creating a leak, since all the data previously referenced by data wouldn't have been deleted.
But I have two questions:
1- Is this the only 'guideline'? I.e. define a destructor if the class has member pointers or if it's managing a resource? Or is there anything else?
2- Are there cases when I should not delete member pointers? What about references?
You need to define a destructor if the default destruction does not suffice. Of course, this just punts the question: what does the default destructor do? Well, it calls the destructors of each of the member variables, and that's it. If this is enough for you, you're good to go. If it's not, then you need to write a destructor.
The most common example is the case of allocating a pointer with new. A pointer (to any type) is a primitive, and the destructor just makes the pointer itself go away, without touching the pointed to memory. So the default destructor of a pointer does not have the right behavior for us (it will leak memory), hence we need a delete call in the destructor. Imagine now we change the raw pointer to a smart pointer. When the smart pointer is destroyed, it also calls the destructor of whatever its pointing to, and then frees the memory. So a smart pointer's destructor is sufficient.
By understanding the underlying reason behind the most common case, you can reason about less common cases. It's true that very often, if you're using smart pointers and std library containers, their destructors do the right thing and you don't need to write a destructor at all. But there are still exceptions.
Suppose you have a Logger class. This logger class is smart though, it buffers up a bunch of messages to Log, and then writes them out to a file only when the buffer reaches a certain size (it "flushes" the buffer). This can be more performant than just dumping everything to a file immediately. When the Logger is destroyed, you need to flush everything from the buffer regardless of whether it's full, so you'll probably want to write a destructor for it, even though its easy enough to implement Logger in terms of std::vector and std::string so that nothing leaks when its destroyed.
Edit: I didn't see question 2. The answer to question 2 is that you should not call delete if it is a non-owning pointer. In other words, if some other class or scope is solely responsible for cleaning up after this object, and you have the pointer "just to look", then do not call delete. The reason why is if you call delete and somebody else owns it, the pointer gets delete called on it twice:
struct A {
A(SomeObj * obj) : m_obj(obj){};
SomeObj * m_obj;
~A(){delete m_obj;};
}
SomeObj * obj = new SomeObj();
A a(obj);
delete obj; // bad!
In fact, arguably the guideline in c++11 is to NEVER call delete on a pointer. Why? Well, if you call delete on a pointer, it means you own it. And if you own it, there's no reason not to use a smart pointer, in particular unique_ptr is virtually the same speed and does this automatically, and is far more likely to be thread safe.
Further, furthermore (forgive me I'm getting really into this now), it's generally a bad idea to make non-owning views of objects (raw pointers or references) members of other objects. Why? Because, the object with the raw pointer may not have to worry about destroying the other object since it doesn't own it, but it has no way of knowing when it will be destroyed. The pointed to object could be destroyed while the object with the pointer is still alive:
struct A {
SomeObj * m_obj;
void func(){m_obj->doStuff();};
}
A a;
if(blah) {
SomeObj b;
a.m_obj = &b;
}
a.func() // bad!
Note that this only applies to member fields of objects. Passing a view of an object into a function (member or not) is safe, because the function is called in the enclosing scope of the object itself, so this is not an issue.
The harsh conclusion of all this is that unless you know what you're doing, you just shouldn't ever have raw pointers or references as member fields of objects.
Edit 2: I guess the overall conclusion (which is really nice!) is that in general, your classes should be written in such a way that they don't need destructors unless the destructors do something semantically meaningful. In my Logger example, the Logger has to be flushed, something important has to happen before destruction. You should not write (generally) classes that need to do trivial clean-up after their members, member variables should clean up after themselves.
A class needs a destructor when it "owns" a resource and is responsible for cleaning it up. The purpose of the destructor is not simply to make the class itself work properly, but to make the program as a whole work properly: If a resource needs to be cleaned up, something needs to do it, and so some object should take responsibility for the cleanup.
For instance, memory might need to be freed. A file handle might need to be closed. A network socket might need to be shut down. A graphics device might need to be released. These things will stay around if not explicitly destroyed, and so something needs to destroy them.
The purpose of a destructor is to tie a resource's lifetime to an object's, so that the resource goes away when the object goes away.
A Destructor is useful for when your classes contain Dynamically Allocated Memory. If your classes are simple and don't have 'DAM', then it's safe to not use a Destructor. In addition, read about the Rule Of Three. You should also add a copy constructor and an overloaded = operator if your class is going to have 'DAM'.
2) Do not worry about References. They work in a different way such as that it "Refers" to another variable (Which means they don't point to the memory).
Will the smart pointer or scoped pointers delete an object when the class has no destructor
If not, why not just leave the scope and let the object be deleted by itself?
All class members are deleted even if you don't have a destructor when the instance is deleted. Memory leaks occur when you deal with pointers:
class A
{
private:
B* b;
};
In this case, b itself will be destroyed when the instance of A is deleted, but the memory it points to will not.
class A
{
private:
SmartPtr<B> b;
};
In the case of smart pointers, which usually have some reference counting and memory cleanup in the destructor, the memory it points to will be explicitly destroyed by its destructor, and the destructor of the smart pointer will be implicitly called when the instance of the containing class is destroyed.
yes. that s what smart pointers are used for.
http://www.boost.org/doc/libs/1_48_0/libs/smart_ptr/smart_ptr.htm
http://en.wikipedia.org/wiki/Smart_pointer
What is a smart pointer and when should I use one?
Yes, smart pointer deletes the object irrespective of whether class has destructor or not. Note that smart pointers are used with objects allocated on heap (using new) and these object won't release memory when they go out of scope, you need to explicitly delete them. Smart pointers will remove this process of explicitly deleting them.
The pointer to the object itself will be deleted. However if there is any dynamically allocated data in the class it will not get freed. The idea of having a destructor is to be able to post-process the class object and mainly - free any resources taken.
new and delete do two things.
new allocates memory and gets an object to construct itself in that memory space.
delete first gets the object to destruct itself then releases the memory.
Note that some smart pointers can be given a custom deleter which doesn't call delete on the object but whatever you ask it to do. There may be occasions when you wish to pass it a no-op.
Your point is well taken; there aren't that many uses for smart pointers
in C++, since most of the time where they might be relevant, you'd be
better off using value semantics, and copying. In the case of
scoped_ptr, the most frequent use is when the actual object is
polymorphic:
scoped_ptr<Base> pObj = condition
? static_cast<Base*>( new Derived1 )
: static_cast<Base*>( new Derived2 );
(Regretfully, at least one of the static_cast is necessary.)
If you are dealing with a container of polymorphic objects, you'll need
shared_ptr instead, and if you're returning a polymorphic object, or
otherwise passing it around, you will use unique_ptr if you can
guarantee its availability, and auto_ptr otherwise—in some cases
where you're passing it around, shared_ptr might be more appropriate.
In the case of returning an object or passing it around, the cost of
copying it might also be a motive for using a smart pointer, even if the
object isn't polymorphic. In such cases, I'd still use value semantics
(i.e. copying and assigning the object itself) unless I had a
performance problem.
Note that smart pointers aren't only used for memory management. I
regularly use auto_ptr in the interface of queues between threads:
once the object has been inserted into the queue, it no longer belongs
to the sending thread; auto_ptr expresses these semantics exactly,
with the auto_ptr in the sending thread becoming invalid. Or a
modifiable singleton (something which should be very, very rare) might
acquire a lock in its instance function, and return a shared_ptr
which frees the lock in its final destructor. I've also used smart
pointers in one or two cases to ensure transactional semantics: in one
case, for example, the objects were in a number of different sets (which
held pointers to them, of course), ordered according to different
criteria. To modify an object, you acquired a shared pointer to it; the
function which returned this shared pointer also removed the objects
from the sets, so that you could safely modify the key values as well,
and the final destructor reinserted them into the sets according to the
new keys. And so on—there are any number of uses for smart
pointers that have nothing to do with memory management or object
lifetime.
I have a method that has a few pointers as parameters. This method can be called with either named pointers from the callee or dynamically create a pointer to a new object and pass it in as an argument directly as the method is being called.
myClass *myPtr = new myClass(...);
myMethod(myPtr);
Verus
myMethod(new myClass(...));
The problem is that if both of these are valid options, how does one properly free the passed in pointer? Deleting myPtr within myMethod will cause a crash if myPtr is ever accessed again within the program. If I don't delete myPtr, the second option will cause a memory leak if it is used. There are benefits for using both options so both shouldn't break the program.
Aside from using STL, what are some solutions to this problem? Would I have to implement my own garbage collector?
I would say, in this case caller should be responsible for freeing the object. You can consider various options, simplest is:
myClass myInstance = myClass; // or myClass(arg1, arg2, ...)
// and the pass it to your method like this:
myMethod(&myInstance);
You could also consider some smart pointer options like std::tr1::shared_ptr or something from boost.
UPDATE: If your method should be able to get NULL-pointer as its argument, there's no problem at all:
// this is your method declaration:
void myMethod(const myClass *myPtr);
// in your tests or wherever in your code you can call it like
myClass myInstance = myClass; // or myClass(arg1, arg2, ...)
myMethod(&myInstance);
// or like this:
myMethod(NULL);
// for as long as your method has something like this in it:
if (myPtr)
myPtr->someMethod();
You can use a smart pointer for that, like shared_ptr from boost.
If not you need to state clearly who owns the object. If you are going to take over the ownership or leave it to the caller.
If you leave it to the caller, using the form function(new whatever()) wouldn't be a good idea, but the leak would be responsibility of the caller.
If you intent to take over the ownership, creating a sink method, choosing a proper name would be a good idea, of course you'd need to delete the objects by yourself once you are finished.
First thing, you need to assign ownership of the object: you need to have a consistent strategy (and enforced!) as to "who" has the right to delete an object. Once this is clearly established, you shouldn't have the problem you are running into.
Some strategies:
Object is leased: ownership is retained by lender
Object is given: ownership is transferred
Second, for tracking usage of an object, you need an infrastructure such as "smart pointers". Here you have 2 categories to care about:
Object is "singly referenced" i.e. only one "user"
Object is "multi referenced" i.e. more than one "user" at one point in time
For (1), the "tracking information" is the pointer itself whereas in (2) you need more infrastructure.
You should use some sort of smart pointer.
For this simple case ever auto_ptr is fine but in general you should use scoped_ptr or shared_ptr.
If you have some unexplained phobia against STL or boost, you can always pull your own smart pointer class with relative ease (if you don't require super exception safety).
This is a all about ownership.
You need to decide who has ownership (or is there shared ownership).
Basically passing pointers is a very bad idea and NOT very C++ like (this is basically a C interface as there is no concept of ownership). In a C++ program you should define your interfaces (functions) with a very clear sense of ownership transfer.
You have a couple of options.
The function does not have ownership and can not be NULL.
In this case you should pass by reference
The function does not have ownership but may be NULL.
Pass as a pointer and add comments that ownership is not being transferred. This is the worst situation and you should try and avoid this as the semantics are not clearly expressed by the code.
The function takes ownership.
In this case I would suggest using std::auto_ptr as it explicitly indicates that ownership is being transferred to the function.
The function shares ownership.
In this case some form of shared smart pointer like boost::shared_ptr or std::tr1::shared_ptr
In your case I would suggest 1 or 2 depending on the situation.
It is obviously that the function can not delete the pointer as it sometimes may not have ownership. Thus the ownership remains on the side of the caller. So the caller must call the delete as appropriate. Hopefully via some smart pointer mechanism.
You need to decide on the ownership, either:
Caller owns object: object is LOANED to function, Caller is responsible for allocation and deletion.
Function owns object: object is DONATED to function, Caller is responsible for allocation, callee (function) is responsible for deletion.
Use a reference counting via a shared pointer to avoid the problem.
( 2 is ugly because it means that different code is responsible for allocation and deletion, but that might be the correct solution for your case - it also means making copies of the argument if the caller wants to keep the object).
Both of these are valid options in the c++ syntax sense, but I'd argue that the second option is bad software design in almost all cases, and allowing both options in one function might even be bad software design in all cases.
Either the calling class creates the object, calls the method, and deletes the object,
or the calling class creates the object, calls the methon, and expects the method to delete the object.
I see no good reason why both options should be considered reasonable in one method call. It should be clear from documentation or comments which version the method uses, and it is then up to the developer to use that method, or suffer the consequences.
The common behavior is for functions neither to create nor to destroy objects. However, there are functions that do. Common jargon is "sources and sinks". A very useful convention, if you're not using more versatile smart pointers, is to use std::auto_ptr<T> for both sources and sinks. A "source" function returns the object created as an auto_ptr<T>, whereas a sink takes an argument of type auto_ptr<T>.
The benefit is that even if you forget the return value of a source function, you won't have a memory leak. At the end of the statement, the returned auto_ptr destroys the object returned. And similarly, it is obvious that the argument passed in to a void sink(auto_ptr<T> unreferenced) { } will be destroyed before sink returns.
The memory should be freed by its owner. Usually, the owner is the entity that allocated the memory, but in some cases you may allow ownership to be transferred.
void foo() {
myClass* p = new myClass(); // foo owns the pointer, so foo should release it again
}
void foo() {
boost::shared_ptr<myClass> p = new myClass(); // foo allocates the memory, but *transfers* ownership to the smart pointer. The smart pointer is now responsible for freeing the object. (This is true for all types of smart pointers, including boost::scoped_ptr, std::auto_ptr or the C++0x std::unique_ptr.
}
void foo() {
ScopedMyClass x; // ScopedMyClass is some class wrapper which *internally* calls `new myClass`, and so owns the allocation and is responsible for freeing it before the end of the wrapper class' lifetime.
}
In your case specifically, if myMethod doesn't allocate the memory, then it should not free the memory either.
As for how to handle this:
myMethod(new myClass(...));
Just don't do that. If you allocate memory, you need to take ownership of it. Store the pointer first, so you can delete the memory:
myClass* p = new myClass(...);
myMethod(p);
delete p;
or even better, *don't dynamically allocate the object in the first place, eliminating the question of ownership:
myMethod(myClass(...));
I can't comment yet but .. While I would normally argue strongly for the 'creator owns it' paradigm (can you really prove anything else correct?) , I think that the insistence on having the
myMethod(new myClass(...));
usage pretty much requires ownership to be transferred. Perhaps it would be prudent to ask what you're attempting to accomplish with this usage, and could it be handled in another way? Like an overload that takes a reference to the temporary instead of a pointer?
myMethod(myClass& a) { return myMethod(&a); }
myMethod(myClass(...))
Well, I suppose I'll add my little stone to the edifice... though I am not sure it will even be read.
This is a matter of ownership of the memory, it is the role of your interface to convey this meaning: "Will this method take ownership or not".
To better express ownership, it is usually bad to use raw pointers. The STL has the bastard auto_ptr which is better suited to the task (I am waiting for the upcoming unique_ptr rather impatiently there).
For a method, there are several ways to accept parameters:
// Value
void method(T);
// Reference
void method(T&);
// Pointer
void method(T*);
// Smart Pointer
void method(std::auto_ptr<T>);
I skipped the cv-qualification bit because it's irrelevant there.
The point is that out of these 4 solutions, the intent is clear:
Value / Reference / Pointer: the caller is responsible for the memory
auto_ptr the method takes ownership of the memory, this means that the caller cannot use the variable afterward
std::auto_ptr myT = std::auto_ptr(new T());
method(myT);
assert(myT.get() == 0); // myT does not hold anything any longer!
Of course, that's why auto_ptr is a wild beast out there, since it does not respect the convention that a copying an object leaves the copied object apparently unchanged: normally all the public methods should give the same result before and after, reference counting being a corner case here if you expose it.
So, your interface should be clearer if whether or not the caller should expect the method to take ownership or not, a simple way is to use overloading.
void method(T*); // do something
void method(std::auto_ptr<T> p)
{
method(p.get());
}
Easy enough, you are now clear on who handles the memory!
With the same reasonment you can also use this overloading trick to automatically check a pointer for nullity.
void method(T&); // do something
void method(T* p)
{
if (p) method(*p); else throw NullPointer("method");
}
But I would avoid abusing the trick, you'll end up with thousands of methods.
So just remember: ownership semantic is best expressed in CODE rather than in comments.
Which you will immediately mix with Use RAII to manage resources which means here that you should never allocate memory to a raw pointer: use a smart pointer to express ownership of the resource, and a raw pointer to point to existing objects you do not own (and that might possibly be null, otherwise a reference is better ;) ).
I'd like the destructor of my class to delete the entire object except for one of the members, which is deleted elsewhere. First of all, is this totally unreasonable? Assuming it's not, how do I do this? I thought that created an destructor with an empty body would prevent all the members from being deleted (because the destructor wouldn't do anything), but that doesn't seem to be the case.
Short answer: You don't.
Longer answer: If the "member" is actually a pointer to some other allocation, you can arrange to not delete the other allocation.
But usually, if you allocated the other block in the constructor, you want to delete it in the destructor. Anything else will require careful handling of the "ownership" of the block in question. It will be a lot like memory management in plain c. Possible, but fraught with danger.
Good luck.
Depends on what you mean by "deleted". If they aren't in a smart pointer, and aren't explicitly deleted, then they aren't deleted. Members that are just part of the class:
class Bar {
//...
private:
Foo foo;
};
Aren't deleted by the destructor (because they weren't dynamically allocated), they are just destroyed. They "live" inside the class, so once it is destroyed, it's gone.
If you are looking the share "ownership" between two locations, what you want is a dynamically allocated shared_ptr:
#include <memory>
class Bar {
// ...
private:
std::tr1::shared_ptr<Foo> foo;
};
If the member is contained by value (not by pointer or by reference) then you can't prevent it from being deleted and you shouldn't want to.
If you want to delete it elsewhere instead, then make it contained by pointer or by reference.
class House
{
Door door; //contained by value, will be destroyed when the House is
}
class House
{
Door& door; //contained by reference, will not be destroyed when the House is
}
The code in the destructor is only to delete members that are dynamically allocated. The destruction of members is not optional, you can only control the deallocation of what you explicitly allocated before (with operator new).
What you want to do can be obtained using a shared_ptr, in which both your class and the external code share a pointer to the same external object. This way, only when all the pointers to that object go out of scope it will be deleted. But beware not to do circular references, shared_ptr has no "garbage collector" wisdom.
Of course you could use a regular pointer shared by those places, but this is in most cases a bad idea, prone to give you headaches about proper resource deallocation later.
First of all, if the member object is contained by value, it simply goes out of scope when the container object is destroyed, and you cannot prevent it from being deallocated automatically.
If, instead, it is indirectly referenced by your container object (for example with a pointer), you don't have to do anything in particular to not delete it. The destructor doesn't delete anything unless you explicitly write the code to do so.
As for the question whether this is unreasonable, I think it is not, in general, but you have to make clear (usually in the documentation, since C++ has no language support for this concept) what is the object that owns the member in question.
I think that in most cases you're asking for trouble if you don't destruct the entire object in the same action. It sounds like your class should have a clean up method for that member, which is called within the destructor. If for some reason the member has to be destroyed sooner, the method can return early.
First of all, is this totally
unreasonable?
I wouldn't say unreasonable, perhaps questionable.
It's perfectly valid for one class to own and therefore should take care of clean up, while at the same time having a reference or a pointer to that object in another class.
However, it might be questionable if the second class reall should have that pointer or not, I'd prefer to always use a get-method to retrieve that pointer whenever I need it, e.g. by calling a parent class or some resource manager.
If you have dynamically allocated memory for this member it is possible once you have shared the reference to this member before destroying the object and if you ensure the member is not destroyed in the object's destructor. However I think this practice isn't so reasonable.
When you talk about class members being deleted in the destructor, you have to make a distinction between members that are not pointers and those that are. Let's say you have a class like this:
class Foo
{
public:
Foo() {p = new int;}
~Foo(){}
private:
int a;
int *p;
};
This class has 2 data members: an integer a and a pointer to an integer p. When the destructor is called, the object is destroyed, meaning that the destructors for all its members are called. This happens even if the destructor's body is empty. In the case of a primitive type, like an integer, calling its destructor just means that the memory it occupies will be released. However, there is a catch when you destroy a pointer: whatever it points to does not get destroyed by default. For that you have to explicitly call delete.
So in our example, a will be destroyed when the destructor is called, and so will p, but not whatever p points to. If you wish to free the memory to which p points, the destructor for Foo should look like this:
~Foo() {delete p};
So, getting back to your question, all the members of your class which are not pointers will be destroyed no matter what, when the object's destructor is called. On the other hand, if you have members that are pointers, whatever they point to will not be destroyed, unless you specifically call delete for them in the destructor.
How come no one mentioned weak and strong pointers?
A strong pointer is a smart pointer that acts normally.
A weak pointer is a smart pointer that cannot delete itself unless all of the strong pointers are out of scope.
Strong pointer indicates ownership, a weak pointer indicates sharing.
Look at boost.shared_ptr and boost.weak_ptr and Loki's StrongPtr for implementations.
Also take a look at RAII. If you knew RAII you would have known the answer to this question yourself.
It is not unreasonable, but care should be taken to ensure that cleanup of any managed resources is handled implicitly.
(The first managed resource that people generally worry about is memory, but anything that can leak - memory, file handles, IDispatch pointers - should have code which handles the cleanup implicitly).
For managed resources shared by multiple objects (almost certainly the case if "this object" is supposed to have a pointer to something that gets cleaned up by "that object"), you are normally needing either a "reference counted pointer" to manage the object or a "weak pointer", depending on your lifetime requirements.
For managed resources which are not shared (and in particular those that need to be managed properly when exceptions can be thrown), then an auto_ptr or other variant may be more suitable.
The Scott Meyers Effective C++ books were a reasonable starting point for learning about smart pointers, but in practice you should probably just grab a vetted library like Boost and let somebody else worry about getting the obscure corner cases (like what happens if a constructor throws an exception?) right.
This is possible but basically as #dmckee said it is then a ownership issue. If that is the case may be you can go for refcounting. i.e.
class A
{
RefObj* obj;
A()
{
obj = new RefObj;
}
~A()
{
obj->ReleaseRef();
}
}
RefObj
{
int m_iRefCounter;
RefObj()
{
m_iRefCounter = 1;
}
AddRef()
{
m_iRefCounter++;
}
ReleaseRef()
{
m_iRefCounter--
if(m_iRefCounter == 0)
{
delete this;
}
}
}
}