I am under the impression that it is a C++ class contained in a library written by a third party. I tried searching on Google, and I found one post that said it was a good idea to use it. However, it failed to describe exactly what it is and how I can incorporate it into my code. Thanks.
-
1What is unclear about the existing SO questions regarding this topic? If you read them you'll also see that this may be referred to as RAII (Resource Acquisition Is Initialization). For example, [Does ScopeGuard use really lead to better code?](http://stackoverflow.com/questions/48647/does-scopeguard-use-really-lead-to-better-code). – James Adkison Jul 12 '15 at 06:33
-
@JamesAdkison: No, scope guards *are based on* RAII, just as e.g. a `for` loop is based on jumps, but you wouldn't call a `for` loop a jump, would you? `for` loops are at a higher level of abstraction, and are a more specialized concept, than jumps. Scope guards are at a higher level of abstraction, and are a more specialized concept, than RAII. – Cheers and hth. - Alf Jul 12 '15 at 07:57
-
I have a modern, simple, documented, and carefully tested implementation [here](https://ricab.github.io/scope_guard/) – ricab Aug 15 '18 at 22:20
2 Answers
ScopeGuard
was once a particular implementation of scope guards by Petru Marginean and Andrei Alexandrescu. The idea is to let the destructor of a guard object call a user specified cleanup action at the end of a scope (read: block), unless the scope guard is dismissed. Marginean came up with an ingenious idea of declaring a scope guard object for C++03, based on lifetime extension of a reference to const
.
Today “scope guard” is more the general idea.
Scope guards are based on RAII (automatic destructor calls used for cleanup), just as e.g. a for
loop is based on jumps, but one wouldn't ordinarly call a for
loop a jump-based piece of code, because that loses most of the information of what it is about, and likewise one does not ordinarily refer to scope guards as RAII. for
loops are at a higher level of abstraction, and are a more specialized concept, than jumps. Scope guards are at a higher level of abstraction, and are a more specialized concept, than RAII.
In C++11 scope guards can be trivially implemented in terms of std::function
, with the cleanup action supplied in each place via a lambda expression.
Example:
#include <functional> // std::function
#include <utility> // std::move
namespace my {
using std::function;
using std::move;
class Non_copyable
{
private:
auto operator=( Non_copyable const& ) -> Non_copyable& = delete;
Non_copyable( Non_copyable const& ) = delete;
public:
auto operator=( Non_copyable&& ) -> Non_copyable& = default;
Non_copyable() = default;
Non_copyable( Non_copyable&& ) = default;
};
class Scope_guard
: public Non_copyable
{
private:
function<void()> cleanup_;
public:
friend
void dismiss( Scope_guard& g ) { g.cleanup_ = []{}; }
~Scope_guard() { cleanup_(); }
template< class Func >
Scope_guard( Func const& cleanup )
: cleanup_( cleanup )
{}
Scope_guard( Scope_guard&& other )
: cleanup_( move( other.cleanup_ ) )
{ dismiss( other ); }
};
} // namespace my
#include <iostream>
void foo() {}
auto main() -> int
{
using namespace std;
my::Scope_guard const final_action = []{ wclog << "Finished! (Exit from main.)\n"; };
wcout << "The answer is probably " << 6*7 << ".\n";
}
The rôle of the function
here is to avoid templating so that Scope_guard
instances can be declared as such, and passed around. An alternative, slightly more complex and with slightly constrained usage, but possibly marginally more efficient, is to have a class templated on a functor type, and use C++11 auto
for declarations, with the scope guard instance created by a factory function. Both these techniques are simple C++11 ways to do what Marginean did with reference lifetime extension for C++03.

- 142,714
- 15
- 209
- 331
-
The original article by Marginean and Alexandrescu [Generic: Change the Way You Write Exception-Safe Code — Forever](http://www.drdobbs.com/cpp/generic-change-the-way-you-write-excepti/184403758) from way back in December 2000 is still online at Dr. Dobbs – Andrew Walker Jul 12 '15 at 06:55
-
@AndrewWalker: Thanks, adding that ref. (I would have looked it up again and added it, but you saved me the work, and reminded me. :) ). – Cheers and hth. - Alf Jul 12 '15 at 07:53
-
The original link from drdobbs is dead, but you can still find the article on archive.org: https://web.archive.org/web/20121009071337/http://www.drdobbs.com/cpp/generic-change-the-way-you-write-excepti/184403758 (page 1), https://web.archive.org/web/20190317153736/http://www.drdobbs.com/cpp/generic-change-the-way-you-write-excepti/184403758?pgno=2 (page 2), https://web.archive.org/web/20190317164052/http://www.drdobbs.com/cpp/generic-change-the-way-you-write-excepti/184403758?pgno=3 (page 3) – Claudiu Oct 08 '19 at 09:58
-
Scope guards are an example of RRID (resource release is destruction), which is a subset of RAII (resource acquisition is initialization). – Adrian McCarthy Aug 28 '20 at 14:27
-
@AdrianMcCarthy Where did you come across this term *RRID*? I can't seem to find much information about it when doing a simple web search. – 303 Sep 07 '22 at 13:39
-
@303: I don't remember where I found it first, and it does seem search engines are getting worse for queries like this. Many of the articles about RAII are actually about RRID. True RAII is not just about resource cleanup but about tying the resource's entire lifetime to an object's lifetime. If you have an RAII object, then you have the resource. If the resource allocation had failed, the object would not have been created. Thus the RAII/RRID distinction often comes up in debates about exceptions in C++. – Adrian McCarthy Sep 08 '22 at 15:08
It's more of a design pattern than a particular class. It is a way of aquiring/releasing resources (such as files, memory, or mutexes) that is exception safe. unique_lock
in c++11 follows this pattern.
For example, with unique_lock
, instead of writing code like this:
void foo()
{
myMutex.lock();
bar();
myMutex.unlock();
}
You write code like this:
void foo()
{
unique_lock<mutex> ulock(myMutex);
bar();
}
In the first case, what if bar
throws an exception? Then, myMutex
will never be unlocked, and your program would be left in an invalid state. In the second case, however, unique_lock
is programmed to lock the mutex in its constructor, and unlock it in its destructor. Even if bar
throws an exception, the unique_lock
will be destructed as the stack unwinds when the exception travels upward, and so the lock will be released. This saves you having to wrap every call to bar
in a try/catch block and handle exceptions manually.

- 5,941
- 1
- 24
- 39
-
1Of the two explanations provided thus far, this is superior. My only recommendation would be to add in some code for what the unique_lock class would do (which helps make it more obvious). Other than that, great and concise explanation. – easythrees Oct 30 '18 at 22:57
-
In a basic scenario like this, `ulock` is flagged as an unused variable. – Wouzz Sep 13 '20 at 15:33
-
This answer appears to be using the syntax for `std::lock_guard` rather than `std::unique_lock` – MikeOnline Dec 06 '22 at 19:05