Access to a variable outside the try-catch block

I have the following code:

class ClassA { public: ClassA(std::string str); std::string GetSomething(); }; int main() { std::string s = ""; try { ClassA a = ClassA(s); } catch(...) { //Do something exit(1); } std::string result = a.GetSomething(); //Some large amount of code using 'a' out there. } 

I would like the last line to have access to the variable a . How could I achieve this since ClassA does not have a default ClassA() , and I would not want to use pointers? The only way to add a default constructor to ClassA ?

+5
source share
3 answers

You cannot or should not. Instead, you can simply use it in a try block, for example:

 try { ClassA a = ClassA(s); std::string result = a.GetSomething(); } catch(...) { //Do something exit(1); } 

The reason is that since a goes beyond the scope after the try block, referring to the object after that, this behavior is undefined (if you have a pointer to where it was).

If you are interested in a.GetSomething or throw assignment, you can put a try-catch around this:

 try { ClassA a = ClassA(s); try { std::string result = a.GetSomething(); } catch(...) { // handle exceptions not from the constructor } } catch(...) { //Do something only for exception from the constructor exit(1); } 
+9
source

You can use some optional or just use std::unique_ptr .

 int main() { std::string s = ""; std::unique_ptr<ClassA> pa; try { pa.reset(new ClassA(s)); } catch { //Do something exit(1); } ClassA& a = *pa; // safe because of the exit(1) in catch() block std::string result = a.GetSomething(); //Some large amount of code using 'a' out there. } 
+5
source

Of course, simply extending the try block to include using a is the easiest solution.

Also, if you really plan to exit(1) or otherwise abort the program on error, just don't put a try block here at all. An exception will be thrown, interrupting the program if it is not caught.


One option is to use std::optional . This is the same concept as using a pointer, but it uses automatic allocation and therefore you are less likely to create a memory leak. This is currently an experimental status; you can use boost::optional instead if your compiler does not have std::experimental::optional :

 #include <experimental/optional> using std::experimental::optional; using std::experimental::in_place; // ... optional<ClassA> a; try { a = optional<ClassA>(in_place, s); } catch(...) { // display message or something } std::string result; if ( a ) result = a->GetSomething(); 

I would like to repeat, although this is a little spaghetti style, and it would be better to design your code in different ways so that you do not constantly check if the success or failure was built.

This requires ClassA be movable or copied. in_place is a special argument that calls the ideal forwarding constructor for the rest of the arguments. Without in_place you can only give the actual argument to the ClassA constructor; it does not consider implicit conversions in ClassA . (Since optional avoids the ambiguity between copying and initializing a list from an object of the same type).

+2
source

Source: https://habr.com/ru/post/1238257/


All Articles