Re: which pointer
In article <95aa7504-d2d5-47fa-8191-f4484d45e371
@m26g2000yqb.googlegroups.com>, nick_keighley_nospam@hotmail.com says...
// a smart pointer question
#include <memory>
#include <vector>
using namespace std;
class Msg
{
public:
Msg()
{}
};
class Call
{
public:
explicit Call(Msg& msg): msg_(msg)
{}
void process_msg(Msg&)
{}
private:
Msg& msg_;
};
class CallList
{
public:
static void add (Call* call)
{
vec_.push_back( call);
}
private:
static vector<Call*> vec_;
};
vector<Call*> CallList::vec_;
void new_call (Msg& msg)
{
auto_ptr<Call> call_ptr (new Call(msg)); // auto_ptr may not b
what I want
CallList::add (call_ptr.get()); // may throw
Call* call = call_ptr.release();
call->process_msg (msg);
}
int main (void)
{
Msg msg;
new_call (msg);
return 0;
}
this at least compiles.
?> but the aim was to allocate a Call
and store it in CallList. If CallList throws the smart_ptr will
destroy the Call, otherwise process the message and the call remains
in the CallList for more message processing.
smart_ptr would not allow copy or assignment. Release returns the
pointer value and zeros its record. I was going to call it
ExplicitReleasePointer. But then I thought,surely boost have already
done this. Aha! scoped_ptr! Oops no. No release(). The rationale for
this is that scoped_ptr implies no transfer of ownership. But I want
to transfer ownership. That I should use auto_ptr if I want transfer
of ownership semantics.
It seems to me that the above code does what you want, right? Coming
into this conversation late, but based on the above I'd say the code is
what you want. I don't think that any of the other "standard" smart
pointers would give you what you want.
It might be though that what you want is not a smart pointer but a scope
guard:
template < typename T >
struct heap_scope_guard // just does heap memory protection
{
explicit heap_scope_guard(T * t) : resource(t), released(false) {}
~heap_scope_guard() { if (!released) delete resource; }
void release() { released = true; }
private:
T * resource;
bool released;
};
Your code would then be:
void new_call (Msg& msg)
{
Call * call_ptr;
heap_scope_guard<Call> guard(call_ptr);
CallList::add (call_ptr);
guard.release();
call_ptr->process_msg (msg);
}
You could add more, change a few things the way you want. Technically
this would be the "correct" way to do what you want as the auto_ptr is
actually providing more functionality than you actually need/want.
However, I don't think this fact is enough to warrant the extra
development and unit testing for writing a scope guard unless you have
uses for it elsewhere (though it's not really that much). I don't
generally do a bunch of extra development for something THAT pedantic.
Up to you, just a different idea.