[c++] Does C++ support 'finally' blocks? (And what's this 'RAII' I keep hearing about?)

RAII is usually better, but you can have easily the finally semantics in C++. Using a tiny amount of code.

Besides, the C++ Core Guidelines give finally.

Here is a link to the GSL Microsoft implementation and a link to the Martin Moene implementation

Bjarne Stroustrup multiple times said that everything that is in the GSL it meant to go in the standard eventually. So it should be a future-proof way to use finally.

You can easily implement yourself if you want though, continue reading.

In C++11 RAII and lambdas allows to make a general finally:

namespace detail { //adapt to your "private" namespace
template <typename F>
struct FinalAction {
    FinalAction(F f) : clean_{f} {}
   ~FinalAction() { if(enabled_) clean_(); }
    void disable() { enabled_ = false; };
  private:
    F clean_;
    bool enabled_{true}; }; }

template <typename F>
detail::FinalAction<F> finally(F f) {
    return detail::FinalAction<F>(f); }

example of use:

#include <iostream>
int main() {
    int* a = new int;
    auto delete_a = finally([a] { delete a; std::cout << "leaving the block, deleting a!\n"; });
    std::cout << "doing something ...\n"; }

the output will be:

doing something...
leaving the block, deleting a!

Personally I used this few times to ensure to close POSIX file descriptor in a C++ program.

Having a real class that manage resources and so avoids any kind of leaks is usually better, but this finally is useful in the cases where making a class sounds like an overkill.

Besides, I like it better than other languages finally because if used naturally you write the closing code nearby the opening code (in my example the new and delete) and destruction follows construction in LIFO order as usual in C++. The only downside is that you get an auto variable you don't really use and the lambda syntax make it a little noisy (in my example in the fourth line only the word finally and the {}-block on the right are meaningful, the rest is essentially noise).

Another example:

 [...]
 auto precision = std::cout.precision();
 auto set_precision_back = finally( [precision, &std::cout]() { std::cout << std::setprecision(precision); } );
 std::cout << std::setprecision(3);

The disable member is useful if the finally has to be called only in case of failure. For example, you have to copy an object in three different containers, you can setup the finally to undo each copy and disable after all copies are successful. Doing so, if the destruction cannot throw, you ensure the strong guarantee.

disable example:

//strong guarantee
void copy_to_all(BIGobj const& a) {
    first_.push_back(a);
    auto undo_first_push = finally([first_&] { first_.pop_back(); });

    second_.push_back(a);
    auto undo_second_push = finally([second_&] { second_.pop_back(); });

    third_.push_back(a);
    //no necessary, put just to make easier to add containers in the future
    auto undo_third_push = finally([third_&] { third_.pop_back(); });

    undo_first_push.disable();
    undo_second_push.disable();
    undo_third_push.disable(); }

If you cannot use C++11 you can still have finally, but the code becomes a bit more long winded. Just define a struct with only a constructor and destructor, the constructor take references to anything needed and the destructor does the actions you need. This is basically what the lambda does, done manually.

#include <iostream>
int main() {
    int* a = new int;

    struct Delete_a_t {
        Delete_a_t(int* p) : p_(p) {}
       ~Delete_a_t() { delete p_; std::cout << "leaving the block, deleting a!\n"; }
        int* p_;
    } delete_a(a);

    std::cout << "doing something ...\n"; }

Hopefully you can use C++11, this code is more to show how the "C++ does not support finally" has been nonsense since the very first weeks of C++, it was possible to write this kind of code even before C++ got its name.

Examples related to c++

Method Call Chaining; returning a pointer vs a reference? How can I tell if an algorithm is efficient? Difference between opening a file in binary vs text How can compare-and-swap be used for a wait-free mutual exclusion for any shared data structure? Install Qt on Ubuntu #include errors detected in vscode Cannot open include file: 'stdio.h' - Visual Studio Community 2017 - C++ Error How to fix the error "Windows SDK version 8.1" was not found? Visual Studio 2017 errors on standard headers How do I check if a Key is pressed on C++

Examples related to exception

Connection Java-MySql : Public Key Retrieval is not allowed How to print an exception in Python 3? ASP.NET Core Web API exception handling Catching FULL exception message How to get exception message in Python properly What does "Fatal error: Unexpectedly found nil while unwrapping an Optional value" mean? what does Error "Thread 1:EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)" mean? Argument Exception "Item with Same Key has already been added" The given key was not present in the dictionary. Which key? sql try/catch rollback/commit - preventing erroneous commit after rollback

Examples related to raii

Does C++ support 'finally' blocks? (And what's this 'RAII' I keep hearing about?) throwing exceptions out of a destructor General guidelines to avoid memory leaks in C++

Examples related to finally

Try-catch-finally-return clarification In Java, what purpose do the keywords `final`, `finally` and `finalize` fulfil? Java Try Catch Finally blocks without Catch Does C++ support 'finally' blocks? (And what's this 'RAII' I keep hearing about?)

Examples related to c++-faq

What are the new features in C++17? Why should I use a pointer rather than the object itself? Why is enum class preferred over plain enum? gcc/g++: "No such file or directory" What is an undefined reference/unresolved external symbol error and how do I fix it? When is std::weak_ptr useful? What XML parser should I use in C++? What is a lambda expression in C++11? Why should C++ programmers minimize use of 'new'? Iterator invalidation rules