Reputation: 845
I need to allocate memory, but I would like to do this in a try/catch, but that introduces a new scope, in which the variable is then not available once I'm out of the try-scope. What's the best way to solve this?
try {
auto something = std::make_unique<SomeClass>;
}
catch (std::bad_alloc) {
...
}
// ... lots of code I don't want to include in the try/catch-scope.
something.callSomeMethod();
How to I go about solving this?
Upvotes: 1
Views: 1997
Reputation: 69884
If you really must use something
outside the try/catch block (and no, you really mustn't, but if you insist...) then it's a good idea to make it impossible to give yourself a segfault.
calling a method on a null unique_ptr is a sure way to disaster, plus the initialisation of the unique_ptr requires an un-necessary memory allocation.
Another way is to use boost::optional :
#include <iostream>
#include <boost/optional.hpp>
using namespace std;
int main()
{
class SomeClass { public: int a; void callSomeMethod() const {} };
boost::optional<SomeClass> something{};
try {
something = SomeClass();
// operation that might throw other_exception
}
catch (const std::exception& e) {
std::cout << "bad" << std::endl;
}
// ... lots of code I don't want to include in the try/catch-scope.
if (something) {
something.get().callSomeMethod();
}
return 0;
}
Upvotes: 0
Reputation: 3917
As other answers have mentioned, your code should generally be within the try/catch
block, since it doesn't have any meaning if the exception is caught. I'm not sure what your reason is for not wanting to include the code in the try/catch
, since you're implying something.callSomeMethod()
depends on lots of code
, and lots of code
depends on std::make_unique
. If lots of code
isn't dependent, you can delay std::make_unique
until after lots of code
.
I think it might be worth clarifying, the purpose of exceptions is to abort and handle an exceptional situation. The exceptional situation is that execution of following code can be impacted. So, any code that would be impacted, or transitively code that depends on it, should be included in the try/catch
block. This is the minimal scope, by definition, and it's the scope you should use. Nothing more, nothing less.
Sometimes the code to handle an exception can be shared across functions that throw exceptions, but it's still generally best to narrow the scope and write the necessary specific handling code for each one.
It might be worth noting that almost nothing can be done for std::bad_alloc
, so it's generally not an exception worth catching. Also, you should generally catch exceptions by reference unless you have a reason to do otherwise. So, your code should look something like this...
try {
auto something = std::make_unique<SomeClass>;
// ... lots of code I don't want to include in the try/catch-scope.
something.callSomeMethod();
}
catch (std::exception& e) {
// you dun goofed...
}
Upvotes: 1
Reputation: 638
For posterity, and in case you needed to do something else in your try
block that would not result in an invalid pointer (because, as has been mentioned there is a reason what you're trying to do doesn't work). If you're trying to do something else and still want to execute your operations on something
afterward, the following code will do what you want:
#include <iostream>
#include <memory>
#include <utility>
using namespace std;
int main()
{
class SomeClass { public: int a; void callSomeMethod() const {} };
std::unique_ptr<SomeClass> something{};
try {
something = std::move(std::make_unique<SomeClass>());
// operation that might throw other_exception
}
catch (const other_exception& e) {
std::cout << "bad" << std::endl;
}
// ... lots of code I don't want to include in the try/catch-scope.
something->callSomeMethod();
return 0;
}
Upvotes: 2
Reputation: 155
There is a specific reason why what you are doing shouldn't work. If the code you wrote worked the way you wrote it, then you would be calling callSomeMethod()
on a null object. The right way to do it as Benjamin Lindley said, is to put that code in your try block. That way the variable is in-scope but the method call will only happen if there was not a bad alloc that threw an exception.
Upvotes: 2