I'm not 100% certain I worded the title for this right so here's what I want to be able to do...
I have a class that gets defined like so...
class Animal
{
public:
Animal() : m_name("New Animal")
{
}
Animal(const std::string& name) : m_name(name)
{
}
Animal(const Animal& animal) : m_name(animal.name)
{
}
private:
const std::string name;
};
I then initialize an object of this class like so...
Animal* m_animal = new Animal("Leroy");
At some point in my program, the user will click a button that will cause m_animal to become empty. Meaning that the pet named Leroy should not longer exist..
I assumed I could use delete m_animal, but once I call this I can no longer use m_animal without causing a memory allocation error.
So I guess my question is...
Would me using the following code cause a memory leak since the pet named Leroy was not deleted... and if so what are alternatives on how to get this done?
m_pet = NULL;
The entire process would look like this...
Animal* m_animal = new Animal("Leroy");
Animal* m_animal2 = new Animal("Boo");
std::cout << m_animal.name << endl;
m_animal = NULL;
m_animal = new Animal(m_animal2);
std::cout << m_animal.name << endl;
You do want to use delete m_animal;. You can do this:
std::cout << m_animal.name << endl;
delete m_animal;
m_animal = new Animal(m_animal2);
std::cout << m_animal.name << endl;
After calling delete m_animal, you can no longer use what m_animal pointed to, but you can certainly use the m_animal pointer again.
You could just add a clear member function that (for example) sets the name to an empty string. This means "Leroy" no longer exists, but an Animal in a valid state exists, so you can use it to hold some other animal without deleting the old one and allocating a new one.
This, however, still leaves an Animal object--just one that doesn't have a name. If you want to separate allocation from creation/destruction of the objects in the memory, you can allocate raw memory with operator new, then use a placement new to create an object in that memory. When you want to destroy the object, you can directly invoke its destructor, which will truly destroy the object (but leave the memory allocated).
When you're done with the memory, you can use operator delete to delete the memory.
Aside: this is pretty much what std::vector, for one example, does with its memory block. While it's probably more useful when you're dealing with multiple objects, there's nothing particularly wrong with doing it for a single object either.
Aside #2: in most cases, you don't need (or really want) to use new or delete directly as you've shown above. In quite a few cases, you can use an std::shared_ptr or std::unique_ptr instead, with std::make_shared or std::make_unique to allocate the object.
Sometimes (but not for this mcve), it is simpler to use an init() method.
Though I prefer the initialization list such as you have used here (after the ctor), you will sometimes run into system start up sequence options where the ctor parameter is not yet available and thus can not be filled in by the ctor. This is a particular problem when two or more instances (of same or different class) have pointers to the other (as in working and protect hw control)
So, you might consider the following, which solves sequencing and mutual dependency challenges by providing an init() method.
class Animal
{
public:
Animal()
{
init("New Animal")
}
Animal(const std::string name)
{
init(name);
}
Animal(const Animal& animal)
{
init(animal.m_name);
}
void init(std::string name)
{
m_name.erase(); // clear the previous attribute
// (not really needed here, but included for clarity)
m_name = name; // fill in new attribute
// and continue with both clear (when needed) and init's
// of all the other data attributes
// in an order similar to the initialization list.
// note that the compiler won't be able to notify you
// of out of order initialization issues.
}
private:
const std::string name;
};
So, is init() good for anything else?
You asked
how do I un-initialize an object.
In this case, you can simply use "init(...)" to simultaneously
a) clear out the previous state info (when necessary)
b) initialize the state info as if newly created
and
c) avoid the relatively costly delete and new of the other approach.
If you create an object with the new operator, then you need to delete it with the delete operator.
Animal* animal = new Animal( "Pig" );
// Using the animal ...
delete animal;
animal = nullptr;
You need to use the new - delete pair to avoid memory leaks.
Since these two are pointers to Animal class. This should work too:
std::cout << m_animal->name << endl;
m_animal = m_animal2;
std::cout << m_animal->name << endl;
No need to allocate memory for an animal third time, even if one of them gets deleted before, its inefficient code. Then you should delete only one of these pointers and set them both to nullptr. Using an std::shared_ptr may be a more robust solution though.
Related
I wasn't exactly sure how to title this, but basically, I have this class function that is designed to add a new ability to the vector of abilities in the class.
//Part of class Unit
public:
vector <Ability*> myAbilities;
void AddAbility(Ability * ability)
{
myAbilities.push_back(ability);
cout<<"Ability added"<<endl;
cout<<ability->GetName()<<endl;
ability = NULL;
delete ability;
}
I am pretty sure that the pointer in the parameter basically vanishes when the function is done and when I try to output the abilities name within the main function, it doesn't exist. I prefer the use of this function to be:
AddAbility(new Fireball());
Fireball being a child class of Ability.
How might I add a new ability to the vector of pointers to the class Ability through this function? I'm pretty sure doing it by reference is pointless and there is the chance I just forgot something basic, but I can't seem to pinpoint it.
If you are compiling with C++11, consider using shared pointers, and let the system handle memory management:
per Casper Von B's comment below, unique_ptr seems to be a better fit for your particular situation (updated):
std::vector<std::unique_ptr<Ability>> myAbilities;
void AddAbility(Ability * ability)
{
auto ptr = std::unique_ptr<Ability>(ability);
myAbilities.push_back(std::move(ptr));
cout << "Ability added" << endl;
cout << ability->GetName() << endl;
}
Alternatively, you could just let Ability do all of the constructing/destructing. In general, the class which creates the object should be the class which destroys it.
Additionally, this:
ability = NULL;
delete ability;
.. is likely backwards. When you do perform cleanup, be sure to reverse that order:
delete ability;
ability = NULL;
You delete the ability (so the pointer does not point to anything anymore). In the ability vector, you have this pointer that now doesn't point to anything.
So, don't nullify and delete the pointer. The Ability destruction should be done by the Ability destructor.
And yes, the pointer gets copied in vector, as something like 0x455ff930, but remember that when you delete it, the location of memory 0x455ff930 (that was what the pointer was pointing to) is not associated with ability anymore.
If I have the following example:
test.h
class MyClass
{
public:
MyClass();
std::string name1;
std::string name2;
std::string type1;
std::string type2;
void method1(MyClass &obj1);
void method2(MyClass &obj2);
}
test.cpp
MyClass *mainObject = new MyClass();
MyClass::MyClass()
{
}
void MyClass::method1((MyClass &obj1)
{
//do stuff
mainObject=&obj1; //we populate some of the MyClass variables
}
void MyClass::method2((MyClass &obj2)
{
//do stuff
mainObject=&obj2; //we populate the rest of MyClass variables
}
When should I delete mainObject inside test.cpp? Should I create a destructor in order for the client to delete it?
This is a good example that's best solved by not thinking about it yourself.
Use a shared_ptr<MyClass> mainObject; (either the new C++11 or the Boost version). It will do the delete for you.
Mind you, method1() and method2() should take their argument by shared_ptr too. Currently, they're doing a very bad thing: deleting an object that's passed by reference.
Deleting a pointer variable (pointing to non-0) several times is worse than not deleting it. Because the former can cause hard to find bugs and undefined behavior.
Your code is not correctly written. You should delete mainObject; as soon as you try to assign it with &obj1 or &obj2. But make sure that you do it only first time. Don't delete the pointer if it's pointing to obj1 or obj2.
I feel from this question and previous question of yours, that you are coming from Java/C# background. Better to read a good book on C++ first, you will learn that most of the time you don't need new/delete.
You should delete the pointer when you are done using the object it points to. You should not delete a pointer twice while it is pointing to a single object. You should not delete a pointer if it is pointing to an object that you didn't dynamically allocate with new.
I think that I'd go a slightly different way.
Like this:
test.h
class MyClass
{
public:
MyClass();
std::string name1;
std::string name2;
std::string type1;
std::string type2;
void method1(MyClass &obj1);
void method2(MyClass &obj2);
}
test.cpp
MyClass mainObject; // default c-tor called automatically.
MyClass::MyClass()
{
}
void MyClass::method1(MyClass & obj1)
{
//do stuff
//we populate some of the MyClass variables
mainObject.name1=obj1.name1;
mainObject.type1=obj2.type1;
}
void MyClass::method2(MyClass & obj2)
{
//do stuff
//we populate more of the MyClass variables
mainObject.name2=obj1.name2;
mainObject.type2=obj2.type2;
}
There is no simple way to only populate part of your object without specifying which parts.
But, otherwise, if you don't make mainObject a pointer then you don't need to allocate space for it, that's done automatically. (But, I should object to use of globals unless they are REALLY needed!)
This implementation of what I THINK you're trying to do will completely avoid the need for use of the heap, no need for new/delete.
There should always be a logical owner of any resource, and that owner should delete the resource.
There are cases where it makes sense to have shared ownership, and that is what boost::shared_ptr and similar solutions are for. The last one to give up ownership is then the one to delete the resource.
From all comments it looks like you might actually want the following:
static MyClass mainObject; // Not a pointer. Local to test.cpp
void MyClass::method1()
{
//do stuff
mainObject=*this; // Make a copy of the last object modified.
}
void MyClass::method2()
{
//do stuff
mainObject=*this; // Make a copy of the last object modified.
}
In this way, whether you call foo.method1() or bar.method2, the object on the left side of the . is copied to mainObject. No pointer funkyness needed at all, no new and no delete.
When should I delete mainObject inside test.cpp?
When it is no longer used.
Should I create a destructor in order for the client to delete it?
You only have to create a destructor if some resources of class MyClass have to be released - this is not the case with the shown code. The one you should release (=delete) is mainObject. But anyway, method1(..) and method2(..) are overwriting the mainObject pointer which leads to a dangling pointer (you can't reach the object anymore).
[EDIT]
To answer your question:
can a pointer be deleted several times c++?
Pointers are typically not allocated with new - only the objects they pointing to.
If you mean "can delete be called several times on the same pointer?" the answer is no and would lead to UB. delete on a pointer which is zero is defined and legal.
So I decided to dwelve a bit within the pesty C++.
When I call the delete function on a pointer to a simple class that I created I'm greeted by a Debug Assertion Failure -Expression:_BLOCK_TYPE_IS_VALID(pHead->nBlockUse). I assume this is because I've handled the string manipulation wrong and thus causing memory corruption.
I created a basic class, [I]animal[/I], that has a string defined that can be set through a function.
// name
char * ptrName;
animal::animal(char * name)
{
this->SetName(name);
};
animal::~animal()
{
delete [] ptrName;
}
void animal::SetName(char * name)
{
ptrName = name;
};
When using the above class as shown below the error occurs. I've tried both delete ptrName and delete [] ptrName but to no avail.
animal * cat = new animal("Optimus Prime");
delete cat;
What am I missing?
The string "Optimus Prime" was not dynamically allocated, and thus it is not correct to call delete on it.
The problem comes from deleting a pointer that you don't own. You haven't allocated the string, so you must not delete it. The C string you are using is allocated statically by the compiler.
The problem is that in the setName function you are merely assigning the name to ptrName. In the example, the name is a const char string pointer which you can't delete (it is not allocated on the heap). To avoid this error, you can either use a std::string in the class or allocate a new char arry in the constructor of the animal class and assign the pointer to it. Then, in the destructor you can delete the array.
So I decided to dwelve a bit within the pesty C++.
Then do yourself a favor and use C++ right. That would be to use std::string:
// name
std::string name_;
animal::animal(const std::string& name)
: name_(name)
{
}
//animal::~animal() // not needed any longer
//note: copying also automatically taken care of by std::string
//animal(const animal&)
//animal& operator=(const animal&)
void animal::SetName(const std::string& name)
{
name_ = name;
}
Have a look at The Definitive C++ Book Guide and List. I'd recommend Accelerated C++. It comes with a steep learning curve, but since you already know a bit of C++, it's the 250 pages that might set you on the right track.
As a rule of thumb: Whenever you release a resource (memory or other), and it's not in the destructor of a class whose solely purpose is to manage this one resource, something is wrong with your design. Personally, I become suspicious whenever I feel the need to write a destructor, copy constructor, or assignment operator.
Who has ownership of your string?
For example, when you construct your new animal, you're passing in a string literal - that's not yours to free.
You should consider avoiding char* and just using std::string instead.
If you have to use char*, think about ownership. For example, one option is for you to take a copy of the string (using strdup) and own that. This way you can't be stuck with strange bugs like this
char* szFoo = strdup("my string");
{
animal a(szFoo);
}
// At this point szFoo has been deleted by the destructor of a
// and bad things will start to happen here.
printf("The value of my string %s",szFoo);
EDIT: I know in this case, if it were an actual class i would be better off not putting the string on the heap. However, this is just a sample code to make sure i understand the theory. The actual code is going to be a red black tree, with all the nodes stored on the heap.
I want to make sure i have these basic ideas correct before moving on (I am coming from a Java/Python background). I have been searching the net, but haven't found a concrete answer to this question yet.
When you reassign a pointer to a new object, do you have to call delete on the old object first to avoid a memory leak? My intuition is telling me yes, but i want a concrete answer before moving on.
For example, let say you had a class that stored a pointer to a string
class MyClass
{
private:
std::string *str;
public:
MyClass (const std::string &_str)
{
str=new std::string(_str);
}
void ChangeString(const std::string &_str)
{
// I am wondering if this is correct?
delete str;
str = new std::string(_str)
/*
* or could you simply do it like:
* str = _str;
*/
}
....
In the ChangeString method, which would be correct?
I think i am getting hung up on if you dont use the new keyword for the second way, it will still compile and run like you expected. Does this just overwrite the data that this pointer points to? Or does it do something else?
Any advice would be greatly appricated :D
If you must deallocate the old instance and create another one, you should first make sure that creating the new object succeeds:
void reset(const std::string& str)
{
std::string* tmp = new std::string(str);
delete m_str;
m_str = tmp;
}
If you call delete first, and then creating a new one throws an exception, then the class instance will be left with a dangling pointer. E.g, your destructor might end up attempting to delete the pointer again (undefined behavior).
You could also avoid that by setting the pointer to NULL in-between, but the above way is still better: if resetting fails, the object will keep its original value.
As to the question in the code comment.
*str = _str;
This would be the correct thing to do. It is normal string assignment.
str = &_str;
This would be assigning pointers and completely wrong. You would leak the string instance previously pointed to by str. Even worse, it is quite likely that the string passed to the function isn't allocated with new in the first place (you shouldn't be mixing pointers to dynamically allocated and automatic objects). Furthermore, you might be storing the address of a string object whose lifetime ends with the function call (if the const reference is bound to a temporary).
Why do you think you need to store a pointer to a string in your class? Pointers to C++ collections such as string are actually very rarely necessary. Your class should almost certainly look like:
class MyClass
{
private:
std::string str;
public:
MyClass (const std::string & astr) : str( astr )
{
}
void ChangeString(const std::string & astr)
{
str = astr;
}
....
};
Just pinpointing here, but
str = _str;
would not compile (you're trying to assign _str, which is the value of a string passed by reference, to str, which is the address of a string). If you wanted to do that, you would write :
str = &_str;
(and you would have to change either _str or str so that the constnest matches).
But then, as your intuition told you, you would have leaked the memory of whatever string object was already pointed to by str.
As pointed earlier, when you add a variable to a class in C++, you must think of whether the variable is owned by the object, or by something else.
If it is owned by the object, than you're probably better off with storing it as a value, and copying stuff around (but then you need to make sure that copies don't happen in your back).
It is is not owned, then you can store it as a pointer, and you don't necessarily need to copy things all the time.
Other people will explain this better than me, because I am not really confortable with it.
What I end up doing a lot is writing code like this :
class Foo {
private :
Bar & dep_bar_;
Baz & dep_baz_;
Bing * p_bing_;
public:
Foo(Bar & dep_bar, Baz & dep_baz) : dep_bar_(dep_bar), dep_baz_(dep_baz) {
p_bing = new Bing(...);
}
~Foo() {
delete p_bing;
}
That is, if an object depends on something in the 'Java' / 'Ioc' sense (the objects exists elsewhere, you're not creating it, and you only wants to call method on it), I would store the dependency as a reference, using dep_xxxx.
If I create the object, I would use a pointer, with a p_ prefix.
This is just to make the code more "immediate". Not sure it helps.
Just my 2c.
Good luck with the memory mgt, you're right that it is the tricky part comming from Java ; don't write code until you're confortable, or you're going to spend hours chasing segaults.
Hoping this helps !
The general rule in C++ is that for every object created with "new" there must be a "delete". Making sure that always happens in the hard part ;) Modern C++ programmers avoid creating memory on the heap (i.e. with "new") like the plague and use stack objects instead. Really consider whether you need to be using "new" in your code. It's rarely needed.
If you're coming from a background with garbage collected languages and find yourself really needing to use heap memory, I suggest using the boost shared pointers. You use them like this:
#include <boost/shared_ptr.hpp>
...
boost::shared_ptr<MyClass> myPointer = boost::shared_ptr<MyClass>(new MyClass());
myPointer has pretty much the same language semantics as a regular pointer, but shared_ptr uses reference counting to determine when delete the object it's referencing. It's basically do it yourself garbage collection. The docs are here: http://www.boost.org/doc/libs/1_42_0/libs/smart_ptr/smart_ptr.htm
I'll just write a class for you.
class A
{
Foo * foo; // private by default
public:
A(Foo * foo_): foo(foo_) {}
A(): foo(0) {} // in case you need a no-arguments ("default") constructor
A(const A &a):foo(new Foo(a.foo)) {} // this is tricky; explanation below
A& operator=(const &A a) { foo = new Foo(a.foo); return *this; }
void setFoo(Foo * foo_) { delete foo; foo = foo_; }
~A() { delete foo; }
}
For classes that hold resources like this, the copy constructor, assignment operator, and destructor are all necessary. The tricky part of the copy constructor and assignment operator is that you need to delete each Foo precisely once. If the copy constructor initializer had said :foo(a.foo), then that particular Foo would be deleted once when the object being initialized was destroyed and once when the object being initialized from (a) was destroyed.
The class, the way I've written it, needs to be documented as taking ownership of the Foo pointer it's being passed, because Foo * f = new Foo(); A a(f); delete f; will also cause double deletion.
Another way to do that would be to use Boost's smart pointers (which were the core of the next standard's smart pointers) and have boost::shared_ptr<Foo> foo; instead of Foo * f; in the class definition. In that case, the copy constructor should be A(const A &a):foo(a.foo) {}, since the smart pointer will take care of deleting the Foo when all the copies of the shared pointer pointing at it are destroyed. (There's problems you can get into here, too, particularly if you mix shared_ptr<>s with any other form of pointer, but if you stick to shared_ptr<> throughout you should be OK.)
Note: I'm writing this without running it through a compiler. I'm aiming for accuracy and good style (such as the use of initializers in constructors). If somebody finds a problem, please comment.
Three comments:
You need a destructor as well.
~MyClass()
{
delete str;
}
You really don't need to use heap allocated memory in this case. You could do the following:
class MyClass {
private:
std::string str;
public:
MyClass (const std::string &_str) {
str= _str;
}
void ChangeString(const std::string &_str) {
str = _str;
};
You can't do the commented out version. That would be a memory leak. Java takes care of that because it has garbage collection. C++ does not have that feature.
When you reassign a pointer to a new object, do you have to call delete on the old object first to avoid a memory leak? My intuition is telling me yes, but i want a concrete answer before moving on.
Yes. If it's a raw pointer, you must delete the old object first.
There are smart pointer classes that will do this for you when you assign a new value.
When returning objects from a class, when is the right time to release the memory?
Example,
class AnimalLister
{
public:
Animal* getNewAnimal()
{
Animal* animal1 = new Animal();
return animal1;
}
}
If i create an instance of Animal Lister and get Animal reference from it, then where am i supposed to delete it?
int main() {
AnimalLister al;
Animal *a1, *a2;
a1 = al.getNewAnimal();
a2 = al.getNewAnimal();
}
The problem here is AnimalLister doesnot have a way to track the list of Animals Created, so how do i change the logic of such code to have a way to delete the objects created.
Depending on your usage, there are a couple of options you could go with here:
Make a copy every time you create an animal:
class AnimalLister
{
public:
Animal getNewAnimal()
{
return Animal();
}
};
int main() {
AnimalLister al;
Animal a1 = al.getNewAnimal();
Animal a2 = al.getNewAnimal();
}
Pros:
Easy to understand.
Requires no extra libraries or supporting code.
Cons:
It requires Animal to have a well-behaved copy-constructor.
It can involve a lot of copying if Animal is larg and complex, although return value optimization can alleviate that in many situations.
Doesn't work if you plan on returning sub-classes derived from Animal as they will be sliced down to a plain Animal, losing all the extra data in the sub-class.
Return a shared_ptr<Animal>:
class AnimalLister
{
public:
shared_ptr<Animal> getNewAnimal()
{
return new Animal();
}
};
int main() {
AnimalLister al;
shared_ptr<Animal> a1 = al.getNewAnimal();
shared_ptr<Animal> a2 = al.getNewAnimal();
}
Pros:
Works with object-hierarchies (no object slicing).
No issues with having to copy large objects.
No need for Animal to define a copy constructor.
Cons:
Requires either Boost or TR1 libraries, or another smart-pointer implementation.
Track all Animal allocations in AnimalLister
class AnimalLister
{
vector<Animal *> Animals;
public:
Animal *getNewAnimal()
{
Animals.push_back(NULL);
Animals.back() = new Animal();
return Animals.back();
}
~AnimalLister()
{
for(vector<Animal *>::iterator iAnimal = Animals.begin(); iAnimal != Animals.end(); ++iAnimal)
delete *iAnimal;
}
};
int main() {
AnimalLister al;
Animal *a1 = al.getNewAnimal();
Animal *a2 = al.getNewAnimal();
} // All the animals get deleted when al goes out of scope.
Pros:
Ideal for situations where you need a bunch of Animals for a limited amount of time, and plan to release them all at once.
Easily adaptable to custom memory-pools and releasing all the Animals in a single delete.
Works with object-hierarchies (no object slicing).
No issues with having to copy large objects.
No need for Animal to define a copy constructor.
No need for external libraries.
Cons:
The implementation as written above is not thread-safe
Requires extra support code
Less clear than the previous two schemes
It's non-obvious that when the AnimalLister goes out of scope, it's going to take the Animals with it. You can't hang on to the Animals any longer than you hang on the AnimalLister.
I advise returning a std::tr1::shared_ptr (or boost::shared_ptr, if your C++ implementation does not have TR1) instead of a raw pointer. So, instead of using Animal*, use std::tr1::shared_ptr<Animal> instead.
Shared pointers handle reference tracking for you, and delete the object automatically if there are no references left to it.
The simpliest way is to return smart pointer instead of regular pointers.
For example:
std::auto_ptr< Animal> getNewAnimal()
{
std::auto_ptr< Animal > animal1( new Animal() );
return animal1;
}
If you are able to use TR1 or Boost, you can also use shared_ptr<>.
Kind of a classic issue with pointers and allocated memory. It's about responsibility - who is responsible for cleaning up the memory allocated by the AnimalLister object.
You could store off a pointer to each of those allocated Animals in the AnimalLister itself and have it clean things up.
But, you do have a couple of pointers to Animals sitting there in main() that would be referencing memory that was deleted.
One of the reasons I think the reference counting solutions work better than rolling your own solution.
shared_ptr (which works well),
return a simple pointer and tell the user of your class that it is their animal now, and they have the responsibility to delete it when finished,
implement a 'freeAnimal(Animal*)' method that makes it obvious that deletion of the animal pointer is required.
An alternative way is to simply return the animal object directly, no pointers, no calls to new. The copy constructor will ensure the caller gets their own animal object that they can store on the heap or stack, or copy into a container as they desire.
So:
class AnimalLister
{
Animal getAnimal() { Animal a; return a; }; // uses fast Return Value Optimisation
};
Animal myownanimal = AnimalLister.getAnimal(); // copy ctors into your Animal object
RVO means that returning the object instead of the pointer is actually faster (as the compiler doesn't create a new object and copies it into the caller's object, but uses the caller's object directly).
In a thorough discussion by Scott Meyers, he concludes that using shared_ptr or auto_ptr is the best.
Or you could follow the COM-ish approach, and apply simple reference counting.
When you create the object, give it a reference value of 1 instantly
When anyone gets a copy of the pointer, they AddRef()
When anyone gives up their copy of the pointer, they Release()
If the reference count hits 0, the object deletes itself.
Its ultimately what the shared_ptr does under the hood, but it gives you more control over whats going on, and in my experience easier to debug. (Its also very cross-platform).
I haven't given shared_ ptr too much of a chance in my development as yet, so that may serve your purposes perfectly.
The time to release the memory occupied by an object is when you don't need that particular object any more. In your particular case, the user of a class AnimalLister requested a pointer to a new allocated object of class Animal. So, he's the one that is responsible for freeing memory when he does need that pointer/object any more.
AnimalLister lister;
Animal* a = lister.getNewAnimal();
a->sayMeow();
delete a;
In my opinion, there's no need to over-engineer anything in this case. AnimalLister is just a factory that creates new Animal objects and that's it.
I really like Josh's answer, but I thought I might throw in another pattern because it hasn't been listed yet. The idea is just force the client code to deal with keeping track of the animals.
class Animal
{
...
private:
//only let the lister create or delete animals.
Animal() { ... }
~Animal() { ... }
friend class AnimalLister;
...
}
class AnimalLister
{
static s_count = 0;
public:
~AnimalLister() { ASSERT(s_count == 0); } //warn if all animals didn't get cleaned up
Animal* NewAnimal()
{
++count;
return new Animal();
}
void FreeAnimal(Animal* a)
{
delete a;
--s_count;
}
}