ON_BLOCK_EXIT表示:“我希望在当前代码块退出时做这个动作。”类似的,ON_BLOCK_EXIT_OBJ对于成员函数调用实现相同的功能。
这些宏使用了不太正统的(虽然合法的)花招,这里就不公开了。如果你好奇,你可以到代码里去查看这些宏(因为编译器的bug,用Microsoft VC++的朋友必须关闭“Program Database for Edit and Continue”设定,否则ON_BLOCK_EXIT会有问题)。
每个工具都有推荐的使用方法,ScopeGuard也不例外。你应该象ScopeGuard期望的那样使用它——作为函数中的自动变量。你不应该把ScopeGuard对象用作成员变量,或者在堆上分配它们。为此,供下载的代码中包含了一个Janitor类,它和ScopeGuard做的事情一样,但是采取了更通用的做法——代价是损失了一些效率。因为编译器的bug,Borland C++ 5.5的用户需要使用Janitor而不是ScopeGuard。
class User
{
// ...
string GetName();
void AddFriend(User& newFriend);
private:
typedef vector<User*> UserCont;
UserCont friends_;
UserDatabase* pDB_;
};
void User::AddFriend(User& newFriend)
{
// Add the new friend to the database
pDB_->AddFriend(GetName(), newFriend.GetName());
// Add the new friend to the vector of friends
friends_.push_back(&newFriend);
}
void User::AddFriend(User& newFriend)
{
// Add the new friend to the vector of friends
// If this throws, the friend is not added to
// the vector, nor the database
friends_.push_back(&newFriend);
// Add the new friend to the database
pDB_->AddFriend(GetName(), newFriend.GetName());
}
方法2:原则(politically)上正确的方法
如果你把上面的代码给任何一个C++专家看,它很可能会告诉你:“啊,那方法不好。你应该使用惯用法RAII(Resource Acquisition Is Initialization,资源分配即初始化)[1],在出错的情况下,依靠析构函数来释放资源。”