There are times where I want to be sure that some function call is executed before returning from an other function, or an integer is decremented.
For example consider this code:
void doSomething()
{
try
{
.....
.....
return;
.....
.....
.....
return;
......
} catch ( ... )
}
myvariable--;
}
I want to be sure that myvariable is always decremented, no mater if there is an exception, or a return call. Is there any build in object in C++ for this, or I should create my own class that accepts an std::function and executes it when the object gets out of scope at the object destructor?
For example, in C# there is the try..catch...finally block where in finally you can put any code you want to execute before returning from the function.
Calling a destructor The cases when object goes out of scope, The program goes out of the scope of a function. The program ends. The block initializing local variables of object goes out of scope.
When a pointer goes out of scope, the destructor of the object to which it is pointing is not automatically called. You have to call it yourself, and this happens when you call delete on the node to free up the memory.
Nothing physical happens. A typical implementation will allocate enough space in the program stack to store all variables at the deepest level of block nesting in the current function. This space is typically allocated in the stack in one shot at the function startup and released back at the function exit.
Code within lambda function is executed only once, when the static variable is initialized to the return value of lambda function.
You can write your own, class, that performs some action, in its destructor.
class DoAction
{
public:
DoAction (std::function<void ()> func) : m_func (func)
{
}
~DoAction ()
{
m_func ();
}
private:
std::function<void ()> m_func;
};
And then, create an object of it, in a following way:
DoAction action([&] {/*Code that you want to be executed upon leaving the scope.*/});
Live demo.
I often use std::unique_ptr
for this, using lambda as custom deleter. It's slightly awkward, since you have to do decltype()
for deleter type, but other than that, it saves you writing a 10-liner class.
You can do something like this:
#include <iostream>
template <typename T>
struct decrementer_raii
{
T& var;
decrementer_raii(T& v) : var(v) {}
~decrementer_raii() { --var; }
};
int main()
{
int x = 1;
{
decrementer_raii<int> dec(x);
}
std::cout << x; // should print 0.
}
Live Example
or more like your scenario:
#include <iostream>
template <typename T>
struct decrementer_raii
{
T& var;
decrementer_raii(T& v) : var(v) {}
~decrementer_raii() { --var; }
};
void foo(int& x)
{
decrementer_raii<int> dec(x);
std::cout << x << "\n"; // x is still the original value passed-in (14)
for (int i = 0; i < 10; ++i )
{
if ( i == 4 ) throw 10; // force a throw
}
}
int main()
{
int x = 14;
try {
foo(x);
}
catch(...) {}
std::cout << x; // should print 13.
}
Live Example 2
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With