Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Execute some code when an object goes out of scope

Tags:

c++

c++11

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.

like image 741
Yiannis Mpourkelis Avatar asked Jan 17 '17 20:01

Yiannis Mpourkelis


People also ask

What do you do when an object goes out of scope?

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.

What happens when object goes out of scope C++?

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.

What happens when a variable goes out of scope?

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.

What would you use to execute code only once when?

Code within lambda function is executed only once, when the static variable is initialized to the return value of lambda function.


3 Answers

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.

like image 130
Algirdas Preidžius Avatar answered Oct 04 '22 13:10

Algirdas Preidžius


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.

like image 22
SergeyA Avatar answered Oct 04 '22 12:10

SergeyA


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

like image 24
PaulMcKenzie Avatar answered Oct 04 '22 12:10

PaulMcKenzie