Avoiding heap allocation with throwing constructors

Let's say I have a class Foo

that does not define a default throws

constructor and in a non-standard constructor. When initializing a new object of the type, I would like to catch any exceptions and return, otherwise continue using the object. I notice that it is difficult, if not impossible, to initialize this object on the stack or using a shared pointer because I am trying to avoid memory management.

Error 1

Foo f; // doesn't work, no default constructor
try { f = Foo(...); }

      

Error 2

try {
  Foo f(...)
}
catch(...) {}
// doesn't work, f is inaccessible

      

Error 3

boost::shared_ptr<Foo> pf;
try { pf = new Foo(...); } // no assignment operator

      

Should I...

Foo *f;
try { f = new Foo(...) } // okay, let just manage the memory

      

Is there a way?

Edit

Ok, this is how it works, although not the cleanest. Is there a more "standard" way?

boost::shared_ptr<Foo> pf;
try { pf = boost::shared_ptr<Foo>(new Foo(...)); }

      

+2


source to share


4 answers


The correct persistence approach f

is stack-based to respect the scope:



try {
  Foo f(...);
  ... entire code using f ...
}
catch(...) {}

      

+2


source


Smart pointers have a method reset

:

boost::shared_ptr<Foo> f;
//...
f.reset(new Foo(...));

      



This resolves your Failure # 3 and allows you to do what you want.

+3


source


One solution might be to use boost::optional

(or C ++ 14 std::optional

):

boost::optional<Foo> f;
try { f = Foo(...); }

      

+2


source


Your smart pointer is up and running fine if you use the correct .reset () method.

However, the question is not appropriate for normal use cases, either the class is incorrectly designed or you are using it incorrectly. Normal use should just go ahead like case # 1 with an F inside the block. Or don't try to block and leave the catch upstream.

EDIT: Referring to the latest comments as well as the original issue, I maintain my position that blocking attempts in end-user code are discouraged. In situations where I use third-party components with a specific throwing strategy, if that doesn't suit my needs, I write wrappers converting the exception to an error exception or an error code exception. And use this advanced component.

In this case, the user is concerned about throwing the ctor. So this will be handled by wrapping the ctor in a function:

Foo* new_foo( ARGS )
{
    try{
       return new Foo( ARGS );
    }
    catch( const FooException& )
    {
         return NULL;
    }
}

      

Then you have client code free of try blocks and more importantly, no assignments. It will just be const unique_ptr<Foo> p(new_foo(...))

.

+1


source







All Articles