我在哪里可以为我的 C++ 项目找到一个好的 Scope Guard 实现?
Posted
技术标签:
【中文标题】我在哪里可以为我的 C++ 项目找到一个好的 Scope Guard 实现?【英文标题】:Where can I find a good Scope Guard implementation for my C++ projects? 【发布时间】:2010-08-12 11:56:50 【问题描述】:我最近刚刚了解了 Scope Guard C++ 习语。不幸的是,我找不到任何好的实现。
谁能给我指点 C++ 中一些好的和可用的 Scope Guard 实现?
谢谢,博达·赛多。
【问题讨论】:
以前从未听说过这个 - 其他人骗我,请参阅en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Scope_Guard。恕我直言,这似乎不太有用。而且实现起来很简单——你不需要“找到一个实现”。 @Neil:很有趣,因为它与我对 RAII 相关习语的期望大不相同。我确实想知道成功执行后谁来处理资源。 据我所知,智能指针只有delete
,但使用范围保护你也可以delete []
或free
或fclose()
或close_my_object
等。所以我认为它更好.如果我错了,请纠正我。
智能指针不必只调用delete
。见boost.org/doc/libs/1_43_0/libs/smart_ptr/…。虽然我个人认为 Scope Guard 对于 close_my_object
之类的情况更清晰。
我真的推荐Boost's Scope Exit,他们做得很好。
【参考方案1】:
最初的 ScopeGuard 类包含在 Andrei Alexandrescu 和 Petru Marginean 的 this Dr. Dobb's article 中。 here 提供了一个略微改进的版本,其中包含 Joshua Lehrer 的一些更改。 (Lehrer 的版本是我在项目中使用的版本。)它也包含在 Loki 库中。
Boost 现在有一个ScopeExit 库,它比 ScopeGuard 更强大(因为它可以执行任意代码,而 ScopeGuard 只能调用一个预先存在的函数)。
编辑:话虽如此,Scope Guard 实际上只是 RAII 的一种特定应用,所以你真的应该至少了解如何实现它的概念。
【讨论】:
自从写了这个答案之后,C++11 就出来了,在它之后 - 一个新的 ScopeGuard,比以前好得多;考虑弃用您的答案,转而支持@MikeEllery 的this one。【参考方案2】:ScopeGuard 已包含在 Loki 库中(在 Andrei Alexandrescu 的 Modern C++ Design 中进行了宣传,我相信您已经听说过这本好书),并且已经足够成熟,可以在生产代码中使用,imo。
明确一点:我们正在讨论使用 RAII 编写异常安全代码。
补充阅读(在 *** 上): Does ScopeGuard use really lead to better code?
【讨论】:
是的,我听说过现代 C++ 设计。但是我没有读过这本书,因为它很难理解!我也许能理解每一页中的一句话。 :) @boda 其实我觉得写的比较清楚。我认为问题在于他并不总是完全明确地说明他所说的做事的动机,而是希望你了解它们。 一开始我发现现代 C++ 设计很难,但在阅读了有关 Haskell 的教程并重新阅读了有关模板的内容后,我理解得很好,回想起来我不知道他应该做些什么不同的事情。继续回来看,这本书真的很好 Alexandrescu 的新的 C++11-ish ScopeGuard 现在是愚蠢的一部分,请参阅@MikeEllery 的this answer。【参考方案3】:Folly 库(来自 facebook 的开源)也提供了一个实现(这并不奇怪,因为他们采用了 A.A.):
https://github.com/facebook/folly/blob/master/folly/ScopeGuard.h
我认为这个和这里提到的 MNMLSTC 实现都值得考虑。
【讨论】:
【参考方案4】:让我提供一个基本的 C++20 版本。
#include <concepts>
#include <type_traits>
template <std::invocable Cleanup>
class [[nodiscard]] scope_guard
Cleanup d;
public:
scope_guard(Cleanup&& d) : dstd::forward<Cleanup>(d)
scope_guard(const scope_guard&) = delete;
~scope_guard()d();
;
// allow construction from plain function
template <typename F>
scope_guard(F&&) -> scope_guard<std::decay_t<F>>;
请注意,除非我们需要移动 scope_guard
,否则它会在 Cleanup
可调用对象上增加零内存开销,因为我们不需要以可重置的方式保存它,因为我们不需要移动构造函数,因为我们得到了类模板参数推导。
语言表达能力的一个很好的例子。谢谢组委会!
【讨论】:
【参考方案5】:“Scope Guard”对象只是更广泛的RAII 惯用语的一个实例。
并且没有单一的实现。这是 C++ 程序员必须理解的东西,而不仅仅是复制/粘贴。幸运的是,实现起来也很简单。
你创建了一个代表某种资源的类。当类被实例化(通过其构造函数之一)时,它应该获取资源,如果失败则抛出异常。当类被销毁时,它应该处理资源,执行所有必要的清理。
然后……就是这样。您还必须处理复制构造函数和赋值运算符(通过克隆资源或将这两个函数设为私有,这样它们就不会被调用)。
您不需要找到“一个好的实现”,因为您将自己编写几十个不同的实现。它们写起来很简单,而且它们不容易被重用,因为每个都包装了不同类型的资源。
【讨论】:
谢谢,jalf,我会尝试自己写。男孩,这对我来说会是一个困难的练习吗?我从来没有想过写这么复杂的代码! 一个好的 Scope Guard 类的优点是它可以很容易地在清理时调用任意代码,而不必自己编写几十个不同的实现。【参考方案6】:有人提议将 scope_guard 添加到标准库中。你可以阅读这篇论文,其中包括一个可以复制/粘贴的示例实现,here。实现见第 9.1 节。
【讨论】:
【参考方案7】:MNMLSTC core 有一个modern C++11 implementation 的作用域保护习语。
【讨论】:
以上是关于我在哪里可以为我的 C++ 项目找到一个好的 Scope Guard 实现?的主要内容,如果未能解决你的问题,请参考以下文章
我在哪里可以找到 Spring Boot 包的 SHA256/SHA512 哈希?
我在哪里可以找到一些好的 Android UI 示例? [关闭]
我在哪里可以找到Visual Studio 2017 Enterprise试用版的Xamarin测试记录器?