Passing Pointers -- where to delete them

A

Arv

Hi,

I am a newbie to cpp, am a bit confused with this whole pass by ref vs
pass by pointer stuff...

I am creating a new object on the heap using new. Now if I pass this
pointer to any function, is it okay to assume that the function can
delete that pointer, or should I delete the pointer in my function
only.

And also I read somewhere it is always good to pass objects by
reference, is it true for objects on the stack or for objects created
with new as well..

Thanks
Arv
 
J

jason.cipriani

I am a newbie to cpp, am a bit confused with this whole pass by ref vs
pass by pointer stuff...

The biggest difference between passing by pointer and passing by
reference is syntax (and there are a lot of consequences of that [e.g.
you can have NULL pointers, references mix well with primitive types
in templates, etc.], it is by no means a small difference). But from
the point of view of *what* you are actually passing around; these two
functions are for the most part identical:

void function1 (Object *ptr) {
// here we assume ptr != NULL.
ptr->SomeMethod();
}

void function2 (Object &ref) {
ptr.SomeMethod();
}

void whatever () {
Object *obj = new Object();
function1(obj); // <-- same exact end effect as...
function2(*obj); // <-- ...this line
}

There is another major difference between pointers and references,
although it comes into play more when declaring pointer and reference
variables rather than passing things to functions. A pointer is an
actual variable. It occupies some memory, and it holds the address, in
memory, of something else. A reference, on the other hand, is just
that -- a reference. A reference does not necessarily occupy any
physical memory -- it is more of an alias for something. Also, a
reference can't exist unless it refers to something:

int a;
int *a_ptr = &a;
int &a_ref = a;

That is all OK; but the following:

int *b_ptr; // <--- this is OK
int &b_ref; // <--- this is not, it does not make sense.

.... contains an error. You have to initialize 'b_ref'. A reference
can't exist unless it refers to something. A pointer, on the other
hand, is just a variable like any other.
I am creating a new object on the heap using new. Now if I pass this
pointer to any function, is it okay to assume that the function can
delete that pointer, or should I delete the pointer in my function
only.

In general, you should try to only delete objects in the "opposite" of
the code that you create them in. For example, if you have a function
like this:

void function () {
Object *obj = new Object;
// do something with obj
delete obj;
}

There you instantiate Object at the beginning of the function, so it
makes sense to delete the object at the end of the function. Or
something like this:

void function () {
Object *obj1 = new Object;
if (...) {
Object *obj2 = new Object;
...
delete obj2;
}
delete obj1;
}

There it makes sense to delete the Objects just before they go out of
the scope they were created in. Likewise, if you allocate objects in
the constructor of some class, it makes sense to delete them in the
destructor:

class Something {
public:

Something () {
m_object = new Object;
}

~Something () {
delete m_object;
}

private:
Object *m_object;
};

Or if you have some initialization function that allocates objects, it
makes sense to destroy those objects in the corresponding "cleanup"
function.

The reason I say it's "good" to do it this way in general is just
because, at least when you are just starting to get the hang of it,
following simple sets of rules like that makes it easier to keep track
of what is going on. In reality, there are many, many different idioms
you can follow for object creation and destruction. Really you need to
keep a few things in mind:

1) How long does this object need to live? When will it be safe to
destroy it?

2) Things must happen in a known order -- do not construct code that
has the risk of using an object before it is instantiated, or after it
has been destroyed. Take care not to construct code that destroys an
object that has already been destroyed. One good rule of thumb here is
to try to always clean things up in the reverse order that you have
created them (you don't *have* to do it this way but it makes sense in
many situations), for example:

ObjectA *obja = new ObjectA();
ObjectB *objb = new ObjectB(obja); // maybe this depends on obja
initialize_something(obja, objb); // a made up function
// do stuff; then cleanup in reverse:
cleanup_something(obja, objb);
delete objb;
delete obja;

3) Documentation and comments helps a lot; for example:

// note: do not delete Objects that you pass to this
// function, it will take care of deleting them for
// you!
void function1 (Object *obj);

// note: the caller may safely delete the object
// passed to this function immediately after calling
// it.
void function2 (Object *obj);

4) At any point, if you no longer have a reference or pointer to an
Object you've created with new() available anywhere in your program,
then you have no way of destroying that object. This will cause a
memory leak. For example:

Object *ptr;

ptr = new Object(); // <-- instance #1
ptr = new Object(); // <-- new instance, uh oh!

delete ptr;

In that example you have no way of destroying the first instance you
created. For a brief moment you stored it's address in 'ptr', but then
you stored something else in 'ptr' immediately afterwards, and now you
have no way of accessing that first object again.

That's not a complete list of things to think about. Other people here
may give you some more insight. But that's what I can think of off the
top of my head, and also I have not had any coffee yet to day so I'm
only running at 25% power output or so. :)

Of course, keeping your code exception-safe can require a lot more
logic than the examples I gave above, but I am trying to keep it
simple.
And also I read somewhere it is always good to pass objects by
reference, is it true for objects on the stack or for objects created
with new as well..

Well, like most things that are "always good", it's not necessarily
always good. More accurately: in many cases it is far more convenient
to pass objects by reference because the syntax can be easier to deal
with, the code can be slightly more readable, less documentation may
be required because some ambiguity is removed, and a few other
reasons.

For example, syntax and readability:

// less readable, and uglier syntax
int add2elems (const vector<int> *a) {
if (a->size() < 2)
return 0;
else
return (*a)[0] + (*a)[1];
}

// more readable, and prettier syntax
int add2elems (const vector<int> &a) {
if (a.size() < 2)
return 0;
else
return a[0] + a[1]; // <-- esp. here
}

Here is an example of it being somewhat self-documenting:

// note: DO NOT PASS NULL or this will crash!
void dosomething (Data *data);

// as opposed to:
void dosomething (Data &data);

Where the case with the reference does not require the comment about
not passing NULL; you probably won't pass a NULL reference (I don't
even know if these exist).

Hope that helps; that's at least what I can think of right now. If you
have any more specific questions, they may be easier to answer. You
can also try reading through the results here:

http://www.google.com/search?hl=en&q=pointer+reference+difference&btnG=Google+Search

Some of those results are more valuable than others; you may want to
take things that you read (especially on public internet forums) with
a slight grain of salt and verify by experimenting on your own. Also
if you ask here, you will eventually get the correct answer from
somebody or other, so feel free to post any more questions you
have! :)

Good luck,
Jason
 
S

Salt_Peter

Hi,

I am a newbie to cpp, am a bit confused with this whole pass by ref vs
pass by pointer stuff...

I am creating a new object on the heap using new. Now if I pass this
pointer to any function, is it okay to assume that the function can
delete that pointer, or should I delete the pointer in my function
only.

One doesn't delete a pointer, you may want to delete what is 'at the
pointer' however.
It is not OK for a function to delete or deallocate an object which
was stored on the heap elsewhere.
The responsability of allocation and deallocation is not something you
can seperate and distribute.
In fact, its not a good idea to use new at all, much better to employ
a smart pointer like boost::shared_ptr.
And also I read somewhere it is always good to pass objects by
reference, is it true for objects on the stack or for objects created
with new as well..

Whether Stack allocation or Heap allocation is involved is irrelevent.
Passing objects should always be passed by reference_to_const unless
it's not possible to do so. And the reason is simple: readability and
intention.

For a pass by pointer, the following is ugly at best.
Only the first version is able to offer a guarentee that the pointer
will not be reseated:

void foo(const std::string* const p_s) { ... }
void foo(const std::string* p_s) { ... }
void foo(std::string* p_s) { ... }

while this one's intentions are crystal clear and the relationship
between object and reference is indestructeable:

void foo(const std::string& s) { ... }
 
J

jason.cipriani

P.S. Also search through the archives of this newsgroup. Searching via
http://groups.google.com/group/comp.lang.c++ is a good way to find
things.

I just noticed a very recent thread here entitled "how do I store a
reference":

http://groups.google.com/group/comp.lang.c++/browse_frm/thread/6357a43c00539511

You may want to skim over it. It's not related specifically to your
question, but it does have some valid info about things that you can
and can't do with references.

There are many other posts with little gems of knowledge in them, if
you look for them.

Jason
 
J

jason.cipriani

It is not OK for a function to delete or deallocate an object which
was stored on the heap elsewhere.

More accurately, you should say: it can be very unsafe if a function
deletes or deallocates an object which was stored on the heap
elsewhere if you aren't prepared for it. For example, I would consider
the following to be perfectly legitimate, as long as the comment
describing what was going on was present:

// This function does something, and then it will delete
// the passed-in object! Do not pass NULL, do not pass
// pointers to objects that can't be deleted!
void SomeFunction (SomeObject *so);
The responsability of allocation and deallocation is not something you
can seperate and distribute.

Sure it is; for example, garbage collecting. Or reference counting. Or
an example like SomeFunction() above.
In fact, its not a good idea to use new at all, much better to employ
a smart pointer like boost::shared_ptr.

When learning, I believe it is a good idea to explicitly use new; if
for no other reason than to understand what "smart pointers" are
actually doing for you. I am not a believer in using tools like
boost::shared_ptr without knowing what is going on under the hood.

To clarify this, though, when he says "its not a good idea to use
new", he actually means "using new instead of a smart pointer leaves
you with a lot more opportunity for errors". There is no specific
reason why new would be "bad" or "evil", but things like
boost::shared_ptr do exist to make life much easier. So once you get a
handle on what's going on, you may switch to boost::shared_ptr (or
your own "smart pointer") and use it to save you some headache.

FYI, the "smart pointer" concept being referred to here is a concept
that typically involves using a template class of some sort to wrap
object creation and destruction, so that the object is automatically
destroyed when it goes out of scope. For example, something like (I
made up MySmartPtr):

void function () {
MySmartPtr<Object> ptr; // automagically new's an Object
Object *x = ptr; // i can use it like a pointer
ptr->MemberFunction(); // same here
} // Object automagically deleted when ptr goes out of scope.

Some smart pointer types even have built in reference counting, which
can be very convenient in many situations.

For now, personally, I still recommend gaining a more complete
understanding of new, delete, pointers, references, and general memory
management techniques before moving into tools that do it for you.
That is just my preferred approach to learning, feel free to take
whatever approach works best for you.
Whether Stack allocation or Heap allocation is involved is irrelevent.
Passing objects should always be passed by reference_to_const unless
it's not possible to do so. And the reason is simple: readability and
intention.

That is debatable. Code comments are also useful; BUT... before you
argue with me read my other post, I also support using references for
readability and intention. I just don't like saying "this is evil,
period". It is good to keep an open-mind, even if some alternatives
are clearly better than others.

But yes, whether it's on the stack or the heap has no bearing on
whether or not you'd want to pass by reference. In the case of passing
pointers to functions that may delete the objects then it could become
an issue; for example, you would not pass an object created on the
stack to SomeFunction() above -- although the comments do say that. On
the other hand, passing by reference eliminates that ambiguity. And
that is still only relevant in the minority case of functions that
delete the objects you pass to them.
For a pass by pointer, the following is ugly at best.
Only the first version is able to offer a guarentee that the pointer
will not be reseated:

void foo(const std::string* const p_s) { ... }
void foo(const std::string* p_s) { ... }
void foo(std::string* p_s) { ... }

You couldn't reseat the pointer outside of foo()'s scope in any of
those cases.

void foo (std::string *p_s) {
std::string localstring;
p_s = &localstring;
}

Is perfectly legitimate. In fact, one *advantage* of using pointers
instead of references is you can do things like this:

// Pass NULL to query the default value from somewhere;
// otherwise pass a string.
void foo (const std::string *s) {
std::string defaultvalue;
if (s == NULL) {
defaultvalue = GetDefaultValueFromSomewhere();
s = &defaultvalue;
}
// now do things with *s.
}

Same deal with output parameters to a function. Perhaps you have this
with references:

// get options a, b, and c
void GetOptions (int &a, int &b, int &c);

But you can do this with pointers:

// get options a, b, and c -- pass NULL for ones you do
// not care about retrieving.
void GetOptions (int *a, int *b, int *c);

AFAIK there is no good equivalent to that that you can do with
references.

So there are advantages and disadvantages to both. As long as you
understand the ups and downs instead of just blindly saying "POINTERS
SUCK" or "REFERENCES SUCK". Pointer parameters have some advantages
too; but I do agree that references are more readable and eliminate
lots of need for documentation; that is definitely true.

Jason
 
J

Jerry Coffin

(e-mail address removed)>, (e-mail address removed)
says...

[ ... ]
I am creating a new object on the heap using new. Now if I pass this
pointer to any function, is it okay to assume that the function can
delete that pointer, or should I delete the pointer in my function
only.

It seems to me that you have the situation a bit backwards. You should
only be using new to create the object if you've already determined that
the object needs a lifetime that can't be satisfied by allocating it
automatically. As a general rule, you want to avoid allocating objects
with new unless you really need to.
And also I read somewhere it is always good to pass objects by
reference, is it true for objects on the stack or for objects created
with new as well..

Having allocated an object on the stack vs. the free store doesn't
change how you should pass it to a function.
 
J

James Kanze

I am a newbie to cpp, am a bit confused with this whole pass
by ref vs pass by pointer stuff...
I am creating a new object on the heap using new.

Why? Do the objects have a specific identity, and a specific
lifetime? If not, there's generally no reason to allocate them
dynamically.
Now if I pass this pointer to any function, is it okay to
assume that the function can delete that pointer, or should I
delete the pointer in my function only.

Neither. Who deletes the object depends on the object---and the
design. In the most frequent cases, the object deletes itself.
In other cases, there may be an explicit lifetime manager, or in
the case of a rollback, the transaction manager may delete the
object. In a few special cases, it might be judicious to use
smart pointers.
And also I read somewhere it is always good to pass objects by
reference, is it true for objects on the stack or for objects
created with new as well..

Again, there are no hard and fast rules, but normally where the
object comes from is not a criteria. There are some cases where
you have to use a pointer (e.g. if it can be null). Other than
that, different shops have different guidelines. Pick one and
use it consistently.
 
J

James Kanze

In general, you should try to only delete objects in the
"opposite" of the code that you create them in.

If you can do this, why use dynamic allocation?
For example, if you have a function
like this:
void function () {
Object *obj = new Object;
// do something with obj
delete obj;
}
There you instantiate Object at the beginning of the function,
so it makes sense to delete the object at the end of the
function.

In such a case, the ONLY thing which makes sense is:

void function()
{
Object obj ;
// ...
}

No new, no delete.

If for some reason, you must use dynamic allocation (e.g.
polymorphism), then you absolutely should use a scoped_ptr here.
But such cases are, in my experience, exceedingly rare, and not
something a beginner is likely to encounter. (The code, as you
have written it, is incorrect, and will leak memory, and
possibly have other untoward effects, in the case of an
exception.)
Or
something like this:
void function () {
Object *obj1 = new Object;
if (...) {
Object *obj2 = new Object;
...
delete obj2;
}
delete obj1;
}
Ditto.

There it makes sense to delete the Objects just before they go
out of the scope they were created in. Likewise, if you
allocate objects in the constructor of some class, it makes
sense to delete them in the destructor:
class Something {
public:
Something () {
m_object = new Object;
}
~Something () {
delete m_object;
}
private:
Object *m_object;
};

Again, why the pointer? (In this case, there are justifications
in specific cases, e.g. the compilation firewall idiom. But
globally, I'd say that given the questions being asked, the
original poster isn't there yet. And of course, in modern code,
you might just use boost::scoped_ptr to implement the
compilation firewall, and not write any delete at all.)
Or if you have some initialization function that allocates
objects, it makes sense to destroy those objects in the
corresponding "cleanup" function.
The reason I say it's "good" to do it this way in general is
just because, at least when you are just starting to get the
hang of it, following simple sets of rules like that makes it
easier to keep track of what is going on. In reality, there
are many, many different idioms you can follow for object
creation and destruction.

The important thing to keep in mind is that dynamic allocation
is used first and foremost to give objects an explicit lifetime.
Anytime the lifetime is defined by scope in some way, you really
should consider not using dynamica allocation at all.
Really you need to keep a few things in mind:
1) How long does this object need to live? When will it be
safe to destroy it?

Or when do you have to destroy it? Many, probably most,
dynamically allocated objects have explicit lifetimes, which
have to be respected. You destruct the object when the
information model you are implemented says to destruct it.
Whether it's safe to or not:). (Seriously, not destructing it
at that moment would be a programming error. So you write the
code to ensure it will be safe, e.g. using the observer
pattern.)
2) Things must happen in a known order -- do not construct
code that has the risk of using an object before it is
instantiated, or after it has been destroyed. Take care not to
construct code that destroys an object that has already been
destroyed. One good rule of thumb here is to try to always
clean things up in the reverse order that you have created
them (you don't *have* to do it this way but it makes sense in
many situations), for example:
ObjectA *obja = new ObjectA();
ObjectB *objb = new ObjectB(obja); // maybe this depends on obja
initialize_something(obja, objb); // a made up function
// do stuff; then cleanup in reverse:
cleanup_something(obja, objb);
delete objb;
delete obja;
3) Documentation and comments helps a lot; for example:
// note: do not delete Objects that you pass to this
// function, it will take care of deleting them for
// you!
void function1 (Object *obj);
// note: the caller may safely delete the object
// passed to this function immediately after calling
// it.
void function2 (Object *obj);

Documentation is essential, but typically, you can assume by
default that a function does not delete something that is passed
to it, UNLESS that is part of its role.
 
J

James Kanze

One doesn't delete a pointer, you may want to delete what is
'at the pointer' however. It is not OK for a function to
delete or deallocate an object which was stored on the heap
elsewhere. The responsability of allocation and deallocation
is not something you can seperate and distribute. In fact,
its not a good idea to use new at all, much better to employ a
smart pointer like boost::shared_ptr.

1. If you're going to use boost::shared_ptr, you had best use
new.

2. Usually (but not always , if you have to allocate an object
dynamically, it is because the object has an explicit,
deterministic lifetime. So boost::shared_ptr will not do
what you want.
 
J

jason.cipriani

[snip]
If you can do this, why use dynamic allocation?
[snip similar questions]

I do not generally use dynamic allocation, but I can definitely think
of plenty of very specific situations where I had no other choice:

1) When using Borland C++ Builder, which requires that all VCL
components are dynamically allocated with 'new', and does not allow
automatic creation of the components.

2) When implementing a class factory, or other similar idioms that are
useful for dynamic creation of objects when you don't know what you
need ahead of time.

3) When dynamic allocation is the only solution; such as an
application where user actions directly lead to the creation and
destruction of objects, and so you don't know what you need to have
created at compile time. This is especially true when you must use
references to the same dynamically created object in many places in
your application, and the containers you are storing them in (perhaps
an std::vector) do not guarantee that their locations in memory will
remain the same (e.g. storing references to objects in an
std::vector<Something>, as opposed to keeping track of them in an
std::vector<Something *>).

I can probably think of more, if I go through the list of applications
I've written and consider when I've had to use new.

I am not arguing for preferring dynamic allocation over other methods.
I'm just stating that there are plenty of situations when there is no
other way, or when other ways just become cumbersome.

Jason
 
J

jason.cipriani

[snip]
If you can do this, why use dynamic allocation?
[snip similar questions]

I am not arguing for preferring dynamic allocation over other methods.
I'm just stating that there are plenty of situations when there is no
other way, or when other ways just become cumbersome.

You are right, most of the examples I gave were too contrived to
warrant use of 'new'. I would definitely not recommend using 'new' in
a context like this if you can avoid it:

{
Object *o = new Object();
{
Object *p = new Object();
delete p;
}
delete o;
}

You should not be using new like that. I once knew a guy who used to
write code like this:

{
int *a = new int;
int *b = new int;

// some arbitrary operations
*a = 3;
*b = *a * 2;
printf("%i", *b);

delete b;
delete a;
}

I have no idea why he did that. From what I understood he came from
some other programming language background where that somehow made
sense to him. DO NOT DO THAT! That is a great example of when NOT to
use new.

On the other hand, for a more complex application or situation where
dynamically allocating memory is the only good way to do it, I see no
problem when using new.

I don't have the time to invent and code entire applications for the
purposes of example on a newsgroup, though, so contrived examples are
going to have to be good enough.

P.S. Another example of when you would want to use 'new' is when you
are using placement new to construct objects in your own memory pool.
There is no other way to construct objects at a given location.
 
I

Ian Collins

[snip]
If you can do this, why use dynamic allocation?
[snip similar questions]

I do not generally use dynamic allocation, but I can definitely think
of plenty of very specific situations where I had no other choice:
I think James was questioning your (snipped) statement "In general, you
should try to only delete objects in the "opposite" of the code that you
create them in." and the example that followed it where clearly dynamic
allocation was inappropriate.
 
A

Arv

[snip]
If you can do this, why use dynamic allocation?
[snip similar questions]
I do not generally use dynamic allocation, but I can definitely think
of plenty of very specific situations where I had no other choice:

I think James was questioning your (snipped) statement "In general, you
should try to only delete objects in the "opposite" of the code that you
create them in." and the example that followed it where clearly dynamic
allocation was inappropriate.

Thanks for all your replies...

I now realise how much thinking I should do before creating objects on
the heap. I was originally thinking that people use heap so that stack
doesnt get bloated with memory. That is why I was thinking sometimes
ppl use new in places where it can be created on the stack...

I got most things clarified now, but I still have a doubt related to
shared_ptr. When I use a singleton object, would a shared_ptr help?
Because when I use new inside the singleton's getInstance method, I am
not sure when to delete it, since it is a static member, i am not sure
putting the delete in the destructor would help. Should I have another
method called resetInstance or something?
 
J

jason.cipriani

I got most things clarified now, but I still have a doubt related to
shared_ptr. When I use a singleton object, would a shared_ptr help?

Not really, because:
Because when I use new inside the singleton's getInstance method, I am
not sure when to delete it, since it is a static member, i am not sure
putting the delete in the destructor would help. Should I have another
method called resetInstance or something?

Well, if it's a singleton, why would you want to reset it? ;-) But if
you must; you have a couple of options. You could do similar to what
you said, create a DeleteInstance() method or something that deletes
the single instance; and then call DeleteInstance() in your cleanup
code or wherever you want. For example:

----- BEGIN EXAMPLE1 -----

#include <cstdio>

class Singleton {

public:

static Singleton * GetInstance () {
if (!_s)
_s = new Singleton();
return _s;
}

static void DeleteInstance () {
delete _s;
_s = NULL;
}

void Hi (const char *where) {
printf("hello from %p in %s\n", (void *)this, where);
}

private:

Singleton () { printf("constructed @ %p\n", (void *)this); }
~Singleton () { printf("deleted\n"); }

static Singleton *_s;

};

Singleton * Singleton::_s;

void function () {

Singleton::GetInstance()->Hi("function");

}

int main (int, char **) {

// do a whole bunch of stuff
Singleton::GetInstance()->Hi("main");
function();

// delete on cleanup; maybe in an exit handler or somewhere else. or
here.
Singleton::DeleteInstance();
return 0;

}

----- END EXAMPLE1 -----

Using something like a boost::shared_ptr is not really necessary
there. Alternatively, you can do it without new at all:

----- BEGIN EXAMPLE2 -----

#include <cstdio>

class Singleton {

public:

static Singleton * GetInstance () {
static Singleton s; // <--- initialized first time here.
return &s;
}

void Hi (const char *where) {
printf("hello from %p in %s\n", (void *)this, where);
}

private:

Singleton () { printf("constructed @ %p\n", (void *)this); }
~Singleton () { printf("deleted\n"); }

};

void function () {

Singleton::GetInstance()->Hi("function");

}

int main (int, char **) {

// do a whole bunch of stuff
Singleton::GetInstance()->Hi("main");
function();

return 0;

}

----- END EXAMPLE2 -----

In that case you can't just "reset" the instance whenever you feel
like it (which, if you have to do this, you should consider whether or
not the "singleton" model is actually what you want), but it will call
the destructor when the program terminates.

Just out of curiosity: what are you doing that you want to use a
singleton class for?

Jason
 
J

jason.cipriani

Unit tests - you would want the object reset before each test.

Maybe. But you need to be very careful when using singletons in an
application that you are eventually going to be doing unit testing on;
especially if your singleton becomes too monstrous and starts to
contain information used in many unrelated situations. For one, your
unit test code couldn't be completely self-contained, in that you have
to modify the singleton's code to generate "fake" states. So if you
were performing many different test cases, the singleton would have to
be aware of the cases. Also, making sure that your simulated
application states *do* in fact represent the state you want to test
is a task that may require testing in itself, because you end up
having to fudge all of the singleton's data to make it completely
valid when in fact you are testing a part of your code that uses only
a very small subset of it.

I usually avoid singletons when I know I'm going to have to do
detailed unit testing -- not because it's necessarily a bad, evil
thing but because I find it much easier to keep everything separate
than lumping it into a singleton class (which, even if I try not to
"lump everything together", the tendency is there -- perhaps it's just
a personal flaw). If you can design the software with unit testing in
mind from the start, you can keep the components a bit more isolated,
and therefore easier to test. I find when I use a singleton it starts
to blur the lines between different parts in my application, just by
it's nature.

In any case, I shouldn't have said "well, if it's a singleton, why
would you want to reset it?"; because it's more a matter of personal
taste, I guess, and I try not to show bias about these kinds of
things. But now that the cat's out of the bag: I do not like
singletons very much. I have never found myself in a situation where
there wasn't a better way.

Jason
 
I

Ian Collins

If you can design the software with unit testing in
mind from the start, you can keep the components a bit more isolated,
and therefore easier to test. I find when I use a singleton it starts
to blur the lines between different parts in my application, just by
it's nature.
Designing with unit tests in mind, or indeed through unit tests
invariably has the benefit of keeping things decoupled. As soon as you
think you need to make tests friends or add methods to support tests,
you know it's time to rethink where you are going with the design.

There's nothing to stop you using a collection of decoupled singletons.
 
J

James Kanze

[snip]
If you can do this, why use dynamic allocation?
[snip similar questions]
I do not generally use dynamic allocation, but I can
definitely think of plenty of very specific situations where I
had no other choice:

I can think of one or two cases myself, but the original context
was responding to relative beginner, and your recommendations
for how to manage memory all seemed to concern situations where
you would normally not use dynamic memory to begin with.
1) When using Borland C++ Builder, which requires that all VCL
components are dynamically allocated with 'new', and does not
allow automatic creation of the components.

The obvious answer to that is to change compilers:).
2) When implementing a class factory, or other similar idioms
that are useful for dynamic creation of objects when you don't
know what you need ahead of time.

But the case of a factory is precisely the case where you do NOT
delete where you new'ed. The case where your recommendation
doesn't hold.
3) When dynamic allocation is the only solution; such as an
application where user actions directly lead to the creation
and destruction of objects, and so you don't know what you
need to have created at compile time.

This is probably the most frequent use of dynamic allocation in
well written code (with "user actions" being understood in its
largest sense---anything which happens outside your code). And
again, it's precisely a case where construction and destruction
don't come in a literal pair; the destruction will occur where
you handle the external event that triggers it (often in the
object itself, i.e. delete this).
This is especially true when you must use references to the
same dynamically created object in many places in your
application, and the containers you are storing them in
(perhaps an std::vector) do not guarantee that their locations
in memory will remain the same (e.g. storing references to
objects in an std::vector<Something>, as opposed to keeping
track of them in an std::vector<Something *>).
I can probably think of more, if I go through the list of
applications I've written and consider when I've had to use
new.

Certainly. Dynamic allocation corresponds to a real necessity.
My point wasn't that it's never appropriate. My point was that
the ways you presented for managing dynamic memory were not
relevant, because they could only be applied in cases where you
normally shouldn't be using dynamic memory.
 
J

James Kanze

[...]
I now realise how much thinking I should do before creating
objects on the heap.

I'd argue that you should do a lot of thinking before creating
objects anywhere:). My own experience is that programming is
about 60% design, 30% coding, and 10% debugging. I've seen
people who inverse those percentages, with 10% design and 60%
debugging, but they tend to take a lot more time to get working
code, and the results are rarely as reliable as what I (and
others I know with similar percentages) deliver.
I was originally thinking that people use heap so that stack
doesn't get bloated with memory.

That occasionally happens as well, although most of the time, in
such cases, the allocations will be hidden in standard classes,
like std::vector. If you do have a single object where sizeof(
MyType ) is a couple of megabytes, you might end up having to
allocate it dynamically, rather than on the heap, but most
applications probably shouldn't have this sort of object to
begin with.
That is why I was thinking sometimes ppl use new in places
where it can be created on the stack...
I got most things clarified now, but I still have a doubt
related to shared_ptr. When I use a singleton object, would a
shared_ptr help?

I don't think so. The whole point of a singleton is that it has
"static" lifetime, so no one using it should destruct it.
Because when I use new inside the singleton's getInstance
method, I am not sure when to delete it, since it is a static
member, i am not sure putting the delete in the destructor
would help. Should I have another method called resetInstance
or something?

There are two idioms, according to what is needed. Most of the
time, it's probably preferable to never destruct the singleton
object---it disappears when the program does, after all of the
destructors of static objects have been called. In such cases,
getInstance() (or just instance()---conceptually, this function
represents the object, and not an action, so it is probably more
appropriate to name it with a noun) allocates, and no one ever
deletes. The instance() function looks something like:

Singleton&
Singleton::instance()
{
static Singleton* theOneAndOnly = new Singleton ;
return *theOneAndOnly ;
}

In the occasional cases where a delete is necessary (or doesn't
hurt), the usual solution is to use a local static:

Singleton&
Singleton::instance()
{
static Singleton theOneAndOnly ;
return theOneAndOnly ;
}

(You'll often see somewhat more complicated versions, for
example, when thread safety is an issue. You probably shouldn't
worry about them for the moment.)
 
J

James Kanze

Unit tests - you would want the object reset before each test.

In such cases, I'll use a separate process for each test. It's
a lot closer to the actual use case. But even then, unit tests
for singletons are somewhat difficult. Typically, the singleton
will look like a memory leak, which, of course, causes the test
to fail---you need to take special precautions to avoid this.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,787
Messages
2,569,629
Members
45,331
Latest member
ElaneLyttl

Latest Threads

Top