Catching exceptions from a constructor means that my instance is out of scope afterward

c++ exception handling best practices
exception handling in constructor and destructor in c++
multiple exception handling in c++
c++ error handling without exceptions
c++ error codes
c++ custom exception
user defined exception in c++
advantages of exception handling

I have a class whose constructor may throw an exception. Here’s some code that will catch the exception:

try {
    MyClass instance(3, 4, 5);
}
catch (MyClassException& ex) {
    cerr << "There was an error creating the MyClass." << endl;
    return 1;
}

But of course no code after the try/catch can see instance because it’s now out of scope. One way to resolve this would be to declare and define instance separately:

MyClass instance;
try {
    MyClass instance(3, 4, 5);
}
...

except that my class doesn’t have the appropriate zero-argument constructor. In fact, this case right here is the only one in which such a constructor would even make sense: the MyClass object is intended to be immutable, in the sense that none of its data members change after construction. If I were to add a zero-argument constructor I’d need to introduce some instance variable like is_initialized_ and then have every method check to make sure that that variable is true before proceeding. That seems like far too much verbosity for such a simple pattern.

What is the idiomatic way to deal with this kind of thing? Do I need to suck it up and allow instances of my class to be declared before they’re initialized?

You should be doing everything you need to do inside the try block:

try {
    MyClass instance(3, 4, 5);

    // Use instance here
}
catch (MyClassException& ex) {
    cerr << "There was an error creating the MyClass." << endl;
    return 1;
}

After all, it is only within the try block that instance has been successfully created and so can be used.

I do wonder whether your catch block is really handling the exception. If you can't do anything to resolve the situation, you should be letting it propagate.

Exceptions and Error Handling, C++ FAQ, How should I handle resources if my constructors may throw exceptions? What does throw; (without an exception object after the throw keyword) mean? Similarly, throw is not a good way of getting out of a loop. saying that you propose using return codes and storing the error information in a namespace- scope, global� The alternate constructor must return the new instance in order to invoke the constructor. Pickling. Objects may have a more complicated state than the simple variables we have encountered so far. Saving it correctly could be tedious and error-prone.

Dynamically allocate the instance using new:

std::unique_ptr<MyClass> instance;
try
{
    instance.reset(new MyClass(3, 4, 5));
}
catch (const MyClassException& ex)
{
    std::cerr << "There was an error creating the MyClass." << std::endl;
    return 1;
}
// use instance as needed...

Error and Exception Handling, After all, if you check for an error condition, then in some sense you expect it to C++ runtime can't resolve which exception instance to match in the first catch clause. constructor(s) might throw, because, though not necessarily fatal to your It's nice to have a message that a programmer stands a chance of figuring out,� • Understand the scope and power of STL features to deal with real-world problems. • Compose your own algorithms without forfeiting the simplicity and elegance of the STL way. Book Description C++ has come a long way and is in use in every area of the industry. Fast, efficient, and flexible, it is used to solve many problems.

You could use a generic helper function that catches exceptions and the future std::optional (or boost::optional) to signal the successful or failed creation of the instance:

template< typename T, typename... Args >
std::optional< T > try_make( Args&&... args )
{
    try {
        return T{ std::forward< Args >( args )... };
    }
    catch( ... ) {
        return {};
    }
}

Using basically this:

auto instance = try_make< MyClass >(3, 4, 5);

Where instance is now an optional<MyClass>. To test the result and separate availablity of the instance from the error case is also simple:

if( auto instance = try_make< MyClass >( 3, 4, 5 ) ) {
    // use *instance, but this code is *not* in the try/catch block!
}
else {
    // creating the instance failed
}

Of course the exception information will be lost this way, but you could go for a less generic function and add some logging in the catch-block depending on your needs.

Top 15 C++ Exception handling mistakes and how to avoid them., Do you use exception handling in your C++ code? Or maybe it's just not the way your legacy code is laid out and you're stuck in the rut. A full discussion of the Stack Unwinding process is beyond the scope of this article When a constructor fails and it does not throw an exception, it leaves the object in� My PL/I knowledge turned out to be quite useful. Within a year I worked on a project for the National Science Foundation. I wrote a very cool program that would verify the accuracy of grant data, basically adding up the rows and columns to make sure that they matched in the application (an inverse spreadsheet).

A variant of Remy's answer, but saving a dynamic allocation using std::optional:

std::optional<MyClass> instance_opt;
try {
    // could use `instance = MyClass(3, 4, 5)`, but that requires you to write a move constructor
    instance_opt.emplace(3, 4, 5);
}
catch (const MyClassException& ex) {
    std::cerr << "There was an error creating the MyClass." << std::endl;
    return 1;
}
MyClass& instance = *instance_opt;
// use instance as needed...

C++ Exception Handling Best Practices: 7 Things To Know, Which means resource allocation done with the constructor Upon throw expression, a copy of the exception object created as the original object goes out of the scope terminate called after throwing an instance of 'std::exception' inside your function to suggest compiler that your function is throwing or� An icon used to represent a menu that can be toggled by interacting with this icon.

OBJ11-J. Be wary of letting constructors throw exceptions, This approach throws an exception in the object's constructor. A thread that can only see a reference to an object after that object has been completely exploit the vulnerable code because the new object instance has gone out of scope. failure can help to ensure that fields are appropriately initialized in catch blocks. A lot of people really dislike C++ because it's a very complex language that often catches one by surprise. Despite this, C++ is undisputed when it comes to striking a balance between abstraction and speed. Those that need to use it for these reasons generally take one of two approaches, while the rest completely dismiss it as an option to begin with. The first consists of restricting its

Exceptions in Java, Part 1: Exception handling basics, Java exceptions are library types and language features used to may fail, catching thrown objects, and cleaning up your Java code after an The object identified by throwable is an instance of Throwable or any of You need to inform the compiler when you throw a checked exception out of a method. An icon used to represent a menu that can be toggled by interacting with this icon.

Constructors (C++), You can define as many overloaded constructors as needed to customize When you declare an instance of a class, the compiler chooses which constructor to invoke The object becomes const after the constructor completes. It is not assigned to any variable and is therefore about to go out of scope. AppDomain.CurrentDomain.UnhandledException fires on any unhandled exception, but provides no means of preventing the application from shutting down afterward. There are, however, some cases where you don’t need to handle exceptions on a worker thread, because the .NET Framework does it for you.

Comments
  • Put all the code inside a function, call the function in the try block.
  • That doesn't make sense. If there's an exception, there's no object, so what possible need could you have with instance?
  • "What is the idiomatic way to deal with this kind of thing?" - don't use try/catch at all, unless you can handle the failure locally.
  • Consider redesigning your class so that the constructor can no longer possibly encounter the error situation which makes him throw the MyClassException in the first place.
  • What are you going to do with the "failed-to-create" object? If you need to store info why it failed to create, store it in the exception.
  • What if the code that uses instance could also throw an exception? Would I just add additional catch blocks for those? My instinct was to put as little code as possible in the try.
  • But if using instance can also throw many exceptions, is it good style to have one try-catch for all exceptions from different parts of code? It will looks better if there will be try-catch for each group of exceptions from each group of code, isn't it?
  • @bdesham Regardless, if you have a try block, it needs to contain everything that depends on the exception not being thrown. That might even mean that it contains the entire content of the function (in which case you could use a function try block).
  • @JosephMansfield, Could, but then your code would fail a review when people don't know what it is :p
  • @bdesham: For the code that uses instance, you have two options. If they throw, can other code continue to use instance, or other objects created in the try block? If so, then you nest another try/catch block within this try block (or better, factor it out into a function with the try/catch block in there). If you can't do anything with instance after those other operations throw, then either add more catchers to the outer try block, or let the exception fall through.
  • Note that you could write MyClass& inst = *instance; after the catch, in order to not need a dereference operator for future accesses of the object
  • Using optional as in my answer saves the heap allocation here, although that's not a big deal.
  • @LightnessRacesinOrbit I can't judge the validity of OPs use-case. If it is valid, the answer might help. Others already pointed out that OP should check if this is really needed in the first place.
  • The last code block is a bit confusing; the OP's goal was that instance be in scope for the remainder of the function, but in that code it is scoped to the if...else block. Recommend just not having that last bit.
  • @M.M I don't think that was the goal. The goal was to work with the instance but outside of the try/catch block, so you don't accidentally catch exceptions from that code, only from the ctor. This can be achieved with my solution (as the comment in the code suggests).