Force creation of objects with new operator

U

Urs Thuermann

I have a class where I want objects to commit suicide by calling

delete this;

Therefore, I want to be sure that all objects are created only using
the new operator. I am thinking about making the constructor and
destructor private and adding a class function to call the constructor
like this:

class Foo {
public:
static Foo *create(int foo) {
return new Foo(foo);
}
void destroy_yourself_when_done() {
delete this;
}
private:
Foo(int foo) { ... }
~Foo() { ... }
};

void user()
{
Foo *f = Foo::create(0);
// do something with f
f->destroy_yourself_when_done();
}

In the real code, the function destroy_yourself_when_done() is of
course more complex and commits suicide only when conditions are met
that the object is no longer needed.

Is this considered a clean approach? Are there better ways?

urs
 
J

Juha Nieminen

Urs Thuermann said:
I have a class where I want objects to commit suicide by calling

delete this;

That's a bit of a dubious design because the calling code has no way
of knowing if the object it's handling got destroyed (other than the
programmer supposedly knowing this from the documentation). If the
calling code keeps using the object afterwards, you get all kinds of
hard-to-find bugs.
 
A

Alf P. Steinbach /Usenet

* Urs Thuermann, on 30.06.2011 11:48:
I have a class where I want objects to commit suicide by calling

delete this;

Therefore, I want to be sure that all objects are created only using
the new operator. I am thinking about making the constructor and
destructor private and adding a class function to call the constructor
like this:

class Foo {
public:
static Foo *create(int foo) {
return new Foo(foo);
}
void destroy_yourself_when_done() {
delete this;
}
private:
Foo(int foo) { ... }
~Foo() { ... }
};

void user()
{
Foo *f = Foo::create(0);
// do something with f
f->destroy_yourself_when_done();
}

In the real code, the function destroy_yourself_when_done() is of
course more complex and commits suicide only when conditions are met
that the object is no longer needed.

Is this considered a clean approach?

No, not in my opinion.

Are there better ways?

I would instead make the destructor non-public.

Much less code, much easier.


Cheers & hth.,

- Alf
 
V

Victor Bazarov

That's a bit of a dubious design because the calling code has no way
of knowing if the object it's handling got destroyed (other than the
programmer supposedly knowing this from the documentation). If the
calling code keeps using the object afterwards, you get all kinds of
hard-to-find bugs.

<shrug> What's the alternative?

V
 
J

Jorgen Grahn

I have a class where I want objects to commit suicide by calling

delete this;

Therefore, I want to be sure that all objects are created only using
the new operator. I am thinking about making the constructor and
destructor private and adding a class function to call the constructor
like this: ....
In the real code, the function destroy_yourself_when_done() is of
course more complex and commits suicide only when conditions are met
that the object is no longer needed.

Is this considered a clean approach? Are there better ways?

There are likely better ways, but /which ones/ depends on your
particular problem, and you haven't shown that one. It seems to me a
communication path from your class is missing, or something -- it
cannot tell its environment "I'm done now; you may destroy me".

/Jorgen
 
A

Alf P. Steinbach /Usenet

* Victor Bazarov, on 30.06.2011 14:18:
The destructor *is* non-public.

Well, then it's a bit redundant with the non-public constructors etc., don't you
think?

I often just don't see things that don't make sense.

To fix this, just insert the word "just", like, "I would instead make just the
destructor non-public".


Cheers & thanks,

- Alf
 
B

Bart van Ingen Schenau

Urs said:
I have a class where I want objects to commit suicide by calling

delete this;

Therefore, I want to be sure that all objects are created only using
the new operator. I am thinking about making the constructor and
destructor private and adding a class function to call the constructor
like this:
class Foo
{
public:
static Foo *create(int foo) {
return new Foo(foo);
}
void destroy_yourself_when_done() {
delete this;
}
private:
Foo(int foo) { ... }
~Foo() { ... }
};

void user()
{
Foo *f = Foo::create(0);
// do something with f
f->destroy_yourself_when_done();
}

In the real code, the function destroy_yourself_when_done() is of
course more complex and commits suicide only when conditions are
met that the object is no longer needed.

Is this considered a clean approach? Are there better ways?

For your goal of requiring dynamic allocation, it is sufficient to make the
destructor non-public. In all other ways of creating an object, the compiler
needs access to the destructor in the same scope as where the construction
takes place. With a non-public destructor, that access is not allowed, so
the compiler must reject the code.

Bart v Ingen Schenau
 
J

Juha Nieminen

Paavo Helde said:
It's the opposite, by putting the deletion inside a member function one
will have more control over when and if it is called, which ought to reduce
the bugs.

The problem is that the object is trying to manage its own lifetime. While
that might sound like a good idea at first, it's actually not. An object
should only manage the lifetime of its member variables, not of itself. It's
the calling code that manages the lifetime of the object itself.

The problem with the object deleting itself is that the calling code has
no way of knowing if that happened. Even if it wanted to explicitly check
"was the object deleted when I called its member function?", there's no
way of doing that (unless you construct a really contrived and inefficient
caching scheme or something).

If an object wants to "delete itself" at some point, the proper design
is to make the class a wrapper that performs the creation and deletion of
the actual object/data appropriately (in other words, the class acts as a
kind of smart pointer to handle the actual object or data).

That has the additional advantage that the class can then be safely
instantiated on the stack, in standard data containers, etc. (Whenever
the calling code can avoid creating objects with 'new', that's always
a positive thing.)
 
K

Keith H Duggar

I have a class where I want objects to commit suicide by calling

delete this;

Therefore, I want to be sure that all objects are created only using
the new operator.  I am thinking about making the constructor and
destructor private and adding a class function to call the constructor
like this:

[snip intrusive lifetime mis-management]
In the real code, the function destroy_yourself_when_done() is of
course more complex and commits suicide only when conditions are met
that the object is no longer needed.

Is this considered a clean approach?
No.

Are there better ways?

Yes. Create a non-intrusive smart pointer, called TerminatorPtr or
what you will. Encapsulate the lifetime management into that smart
pointer. It is hard to go beyond that basic advice unless you give
a concrete and meaningful (in a semantic sense) code example.

KHD
 
J

Juha Nieminen

Paavo Helde said:
Right, and in my (intrusive) smartpointer implementation the object will
end its lifetime by 'delete this' when the last smartpointer is
destroyed.

No, the proper design is for the smart pointer to delete the object when
the last one pointing to it is destroyed.

What possible advantage could there be in the object doing a "delete this"
instead of the smart pointer deleting it? There can only be disadvantages.
 
U

Urs Thuermann

Alf P. Steinbach /Usenet said:
Well, then it's a bit redundant with the non-public constructors etc.,
don't you think?

I wasn't aware that a non-public destructor forces objects of that
class to be created only using the new operator. Now I see, thanks
for that hint.

urs
 
U

Urs Thuermann

Jorgen Grahn said:
There are likely better ways, but /which ones/ depends on your
particular problem, and you haven't shown that one. It seems to me a
communication path from your class is missing, or something -- it
cannot tell its environment "I'm done now; you may destroy me".

In my code I have a class A that has one pointer to an object of class
B and each object of B has list of pointers to all objects of class A
refering to it. Therefore, this is similar to a reference couting
smart pointer but I need the list of referers in class B. That's why
I didn't implement it in a separate smart pointer class:

class A;

class B {
std::list <A *> refs;
~B() { ... }
public:
B(A *a) {
add_ref(a);
}
void add_ref(A *a) {
refs.push_back(a);
}
void rem_ref(A *a) {
refs.remove(a);
if (refs.empty())
delete this;
}
};

class A {
B *b;
public:
A(...) {
if (b = find_matching_B(...))
b->add_ref(this);
else
b = new B(this);
}
~A() {
b->rem_ref(this);
}
};

Currently, I don't see how a wrapper around B that deletes the B
objects could make this cleaner.

urs
 
J

Jorgen Grahn

In my code I have a class A that has one pointer to an object of class
B and each object of B has list of pointers to all objects of class A
refering to it. Therefore, this is similar to a reference couting
smart pointer but I need the list of referers in class B. That's why
I didn't implement it in a separate smart pointer class: ....

Currently, I don't see how a wrapper around B that deletes the B
objects could make this cleaner.

I'm on vacation and won't be replying again in many days, but I want
to mention that I don't consider your posting a reply to mine. I'm
basically saying above: "I don't want to think about a design for this
until I know the whole, real-life problem."

/Jorgen
 

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

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top