ResetClass, is this evil?

J

Jim Langston

I was revisiting some code and I came across this:

Class Client
{
// ...
void ResetClass()
{
COptions SaveOptions = Options;
this->~CClient();
new (this) CClient();
Options = SaveOptions;
}
// ...
};

That use of calling delete and placement new on this seems dubious and I
wonder if it's effects are well defined or undefined.
 
L

Lance Diduck

I was revisiting some code and I came across this:

Class Client
{
    // ...
     void ResetClass()
    {
         COptions SaveOptions = Options;
         this->~CClient();
         new (this) CClient();
         Options = SaveOptions;
    }
   // ...

};

That use of calling delete and placement new on this seems dubious and I
wonder if it's effects are well defined or undefined.

In this example it certainly IS dubious, since your class is Client
and you are newing a CClient.
But assuming your class name is a typo, then the issue is "what
happens if new(this)CClient throws an exception?" Then the object was
destroyed, but failed to reset. You are left with a dead object.
That is bad news, and why this technique --although well defined for
the non-throwing case-- is dubious.

Lance
 
A

Abhishek Padmanabh

Lance Diduck said:
In this example it certainly IS dubious, since your class is Client
and you are newing a CClient.
But assuming your class name is a typo, then the issue is "what
happens if new(this)CClient throws an exception?" Then the object was
destroyed, but failed to reset. You are left with a dead object.
That is bad news, and why this technique --although well defined for
the non-throwing case-- is dubious.

It might have a throw() (non-throwing) constructor. No? The constructor is
not shown if it throws or not.
 
D

Daniel T.

Jim Langston said:
I was revisiting some code and I came across this:

Class Client
{
// ...
void ResetClass()
{
COptions SaveOptions = Options;
this->~CClient();
new (this) CClient();
Options = SaveOptions;
}
// ...
};

That use of calling delete and placement new on this seems dubious and I
wonder if it's effects are well defined or undefined.

I think something like the following would be better, or at least more
idiomatic:

class Client {
Options options; // Options defined elsewhere
public:
Client( const Options& options ); // possibly private?
void swap( Client& c ); // no throw

void resetClass() {
Client tmp( options );
swap( tmp );
}
};
 
K

Kai-Uwe Bux

Jim said:
I was revisiting some code and I came across this:

Class Client
{
// ...
void ResetClass()
{
COptions SaveOptions = Options;
this->~CClient();
new (this) CClient();

You mean Client() not CClient ?
Options = SaveOptions;
}
// ...
};

That use of calling delete and placement new on this seems dubious and I
wonder if it's effects are well defined or undefined.

It is well-defined if Client does not appear as a subobject; see [3.8/7] for
details. That condition will not be met, most of the time if you do OO.

If you want something that works, implement and use an assignment operator:

void reset ( void ) {
Client dummy ( this->options );
*this = dummy;
}

or swap (as long as we don't have move constructors):

void reset ( void ) {
Client dummy ( this->options );
swap( *this, dummy );
}


Best

Kai-Uwe Bux
 
J

jason.cipriani

I was revisiting some code and I came across this:

Class Client
{
// ...
void ResetClass()
{
COptions SaveOptions = Options;
this->~CClient();
new (this) CClient();
Options = SaveOptions;
}
// ...

};

That use of calling delete and placement new on this seems dubious and I
wonder if it's effects are well defined or undefined.

There was a very relevant discussion about this relatively recently,
see:

http://groups.google.com/group/comp.lang.c++/browse_frm/thread/7015a13a431f09b5/

In fact, see my own post (currently #6) in that thread, where I had
brought up using the very same technique (destructor + placement new)
and good reasons for not using it were pointed out.

Jason
 
L

Lance Diduck

It might have a throw() (non-throwing) constructor. No? The constructor is
not shown if it throws or not.- Hide quoted text -

- Show quoted text -

Many compilers do not honor the throw specification, and even if they
did, is it not part of the signature. There is no way to tell, other
than visually tracing the ctor of CClient and all of the members.
This is brittle to say the least.
Like I said, works in the non throwing case, but in the normal case
(like you actually has a std::string member) then it is a bad idea.
Lance
 

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
474,176
Messages
2,570,947
Members
47,498
Latest member
log5Sshell/alfa5

Latest Threads

Top