动态创建的范围防护
我读过有关作用域保护的文章(通用:永远改变编写异常安全代码的方式< /a>) 在 DDJ 中,我了解它们的常见用途。
然而,常见的用途是在堆栈上实例化特定操作的特定堆栈保护,例如:
{
FILE* topSecret = fopen("cia.txt");
ON_BLOCK_EXIT(std::fclose, topSecret);
... use topSecret ...
} // topSecret automagically closed
但是如果我想在运行时安排清理操作,例如当我有循环时怎么办:
{
vector<FILE*> topSecretFiles;
for (int i=0; i<numberOfFiles; ++i)
{
char filename[256];
sprintf(filename, "cia%d.txt", i);
FILE* topSecret = fopen(filename);
topSecretFiles.push_back(topSecret);
ON_BLOCK_EXIT(std::fclose, topSecret); // no good
}
}
显然,上面的示例不起作用,因为 topSecret
将与 for 范围一起关闭。我想要一个范围保护模式,我可以轻松地将我确定在运行时需要的清理操作排队。有这样的东西可用吗?
我无法将范围保护对象推送到标准队列中,因为原始对象(我正在推送的对象)将在此过程中被忽略。推送堆分配的堆栈防护并使用删除 dtor 上其成员的队列怎么样?有谁有更聪明的方法吗?
I've read the article about scope guards (Generic: Change the Way You Write Exception-Safe Code — Forever) in DDJ and I understand their common use.
However, the common use is to instantiate a particular stack guard on the stack for a particular operation, e.g.:
{
FILE* topSecret = fopen("cia.txt");
ON_BLOCK_EXIT(std::fclose, topSecret);
... use topSecret ...
} // topSecret automagically closed
but what if I want to schedule cleanup operations in runtime, e.g. when I have a loop:
{
vector<FILE*> topSecretFiles;
for (int i=0; i<numberOfFiles; ++i)
{
char filename[256];
sprintf(filename, "cia%d.txt", i);
FILE* topSecret = fopen(filename);
topSecretFiles.push_back(topSecret);
ON_BLOCK_EXIT(std::fclose, topSecret); // no good
}
}
Obviously, the above example wouldn't work, since topSecret
would be closed along with the for scope. I'd like a scope guard pattern where I can just as easily queue up cleanup operations which I determine to be needed at runtime. Is there something like this available?
I can't push scope guard objects into a standard queue, cause the original object (the one I'm pushing) would be dismissed in the process. How about pushing heap-allocated stack guards and using a queue which deletes its members on dtor? Does anyone have a more clever approach?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
看来您并不欣赏 RAII 的本质。这些范围保护有时对于本地(“范围”)事物很有用,但您应该尽量避免使用它们,以支持 RAII 真正应该做的事情:将资源封装在对象中。 FILE* 类型确实不擅长于此。
这是一个替代方案:
或者:
或者在“C++0x”(即将推出的 C++ 标准)中:
编辑:因为我非常喜欢 C++0x 中的可移动类型,并且您对它表现出了兴趣:以下是如何将 unique_ptr 与FILE* 没有任何引用计数开销:(
未经测试)
请务必查看 Dave 关于高效可移动价值类型的博客
It seems you don't appreciate RAII for what it is. These scope guards are nice on occasion for local ("scope") things but you should try to avoid them in favour of what RAII is really supposed to do: encapsulating a resource in an object. The type FILE* is really just not good at that.
Here's an alternative:
Or:
Or in "C++0x" (upcoming C++ standard):
Edit: Since I like movable types in C++0x so much and you showed interest in it: Here's how you could use unique_ptr in combination with FILE* without any ref-counting overhead:
(untested)
Be sure to check out Dave's blog on efficient movable value types
呵呵,原来 DDJ 作用域守卫是“可移动的”,不是 C++0x 意义上的,而是与 auto_ptr 是可移动的相同的意义:在复制过程中,新守卫“解雇”旧守卫(就像 auto_ptr 的复制构造函数调用旧构造函数的auto_ptr::release)。
所以我可以简单地保留一个队列,它就会起作用:
顺便说一句,谢谢您上面的回答。它以不同的方式对我提供了信息和教育。
Huh, turns out the DDJ scope guard is "movable", not in the C++0x sense, but in the same sense that an auto_ptr is movable: during the copy ctor, the new guard "dismisses" the old guard (like auto_ptr's copy ctor calls the old one's auto_ptr::release).
So I can simply keep a
queue<ScopeGuard>
and it'll work:By the way, thank you for the answer above. It was informative and educational to me in different ways.