在C++中RAII是很常用的手法,但在一些情況下要多花不少時間去包裝,在Boost中有提供了 ScopeExit (http://www.boost.org/doc/libs/1_57_0/libs/scope_exit/doc/html/index.html),在一些應用下會比正規的 RAII 更加好用。
以 Boost.ScopeExit 官方範例來看,它希望在 addPerson() 中如果有任何一行程式碼失敗了,可以做到 strong guarantee,因此要把 aPerson 從 一_persons中 pop_back() 出來。如果不用 ScopeExit,可以想見在很多地方都會存在著 if(!commit) {m_persons.pop_back()} 這種片段,但有了ScopeExit 就可以有效解決這個問題。
void World::addPerson(Person const& aPerson) {
bool commit = false;
m_persons.push_back(aPerson); // (1) direct action
BOOST_SCOPE_EXIT( (&commit)(&m_persons) )
{
if(!commit)
m_persons.pop_back(); // (2) rollback action
} BOOST_SCOPE_EXIT_END
// … // (3) other operations
[這有可能會有一些失敗的動作,然後就 return / throw exception,然後便自動進入BOOST_SCOPE_EXIT]
…
…
commit = true; // (4) turn all rollback actions into no-op
[就算成功 commit 了,也還是會進入 BOOST_SCOPE_EXIT,但因為有判斷 if(!commit),所以不會進行 pop_back()]
}
BOOST_SCOPE_EXIT()到 BOOST_SCOPE_EXIT_END 中間的程式碼會在離開這個 scope 時被執行,因此可以把 cleanup 相關程式碼放在這裡頭。
以上面這段官方範例來說,它會在最後檢查如果 commit == false,則 pop_back() 剛才 push_back() 進去的 aPerson object。
PS.必需把要用到的變數都寫在 BOOST_SCOPE_EXIT() 的參數列中,才可以存取這些變數。
這篇文章寫的很詳細,值得一讀:
http://boost.cowic.de/rc/pdf/scope_exit.pdf