我认为这是由第三方编写的库中包含的C++类。我尝试在谷歌上搜索,发现有一篇帖子说使用它是一个好主意。然而,它没有详细说明它是什么以及如何将其纳入我的代码中。谢谢。
我认为这是由第三方编写的库中包含的C++类。我尝试在谷歌上搜索,发现有一篇帖子说使用它是一个好主意。然而,它没有详细说明它是什么以及如何将其纳入我的代码中。谢谢。
ScopeGuard
曾经是Petru Marginean和Andrei Alexandrescu提出的一种特定的作用域保护实现链接。其思想是在作用域(即代码块)结束时,除非该作用域保护被解除,否则保护对象的析构函数将调用用户指定的清理操作。Marginean提出了一个巧妙的想法,基于对const
的引用的寿命延长,为C++03声明了一个作用域保护对象。
今天,“作用域保护”更多地是一个通用的概念。
作用域保护基于RAII(自动析构函数调用用于清理),就像for
循环基于跳转一样,但人们通常不会将for
循环称为基于跳转的代码,因为这失去了大部分关于它是什么的信息,同样,人们通常不会将作用域保护称为RAII。 for
循环处于更高级别的抽象层次,并且是比跳转更专业化的概念。作用域保护处于更高级别的抽象层次,并且是比RAII更专业化的概念。
std::function
轻松实现,每个地方都可以通过lambda表达式提供清理操作。
示例:
#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";
}
function
的作用是避免模板化,使得Scope_guard
实例可以被声明为此类,并在各处传递。另一种选择是使用一个基于函数对象类型的类模板,略微复杂且使用受限,但可能更加高效,使用C++11中的auto
进行声明,并通过工厂函数创建作用域保护实例。这两种技术都是使用简单的C++11方法来完成Marginean在C++03中使用引用生命周期扩展所做的事情。这更像是一种设计模式而不是一个特定的类。它是一种获取/释放资源(如文件、内存或互斥锁)的方法,可以保证异常安全。C++11中的unique_lock
遵循了这种模式。
例如,使用unique_lock
,我们可以不写像下面这样的代码:
void foo()
{
myMutex.lock();
bar();
myMutex.unlock();
}
你编写的代码应该像这样:
void foo()
{
unique_lock<mutex> ulock(myMutex);
bar();
}
在第一种情况下,如果 bar
抛出异常会怎样?那么,myMutex
将永远不会被解锁,您的程序将处于无效状态。然而,在第二种情况下,unique_lock
被编程为在其构造函数中锁定互斥量,并在其析构函数中对其进行解锁。即使 bar
抛出异常,当异常向上移动时栈展开,unique_lock
将被解构,因此锁将被释放。这使您无需在每次调用 bar
时包装 try/catch 块并手动处理异常。ulock
被标记为未使用的变量。 - Wouzzstd::lock_guard
的语法,而不是 std::unique_lock
。 - MikeOnline
for
循环基于跳转一样,但你不会称for
循环为跳转,对吧?for
循环处于更高的抽象层次,并且是比跳转更专业化的概念。作用域保护处于更高的抽象层次,并且是比 RAII 更专业化的概念。 - Cheers and hth. - Alf