关于c ++:ScopeGuard的使用是否真的可以带来更好的代码?

关于c ++:ScopeGuard的使用是否真的可以带来更好的代码?

Does ScopeGuard use really lead to better code?

我碰到了多年前由Andrei Alexandrescu和Petru Marginean撰写的这篇文章,其中提出并讨论了一个名为ScopeGuard的实用程序类,用于编写异常安全代码。 我想知道使用这些对象进行编码是否确实可以带来更好的代码,或者它混淆了错误处理,因此,在catch块中更好地呈现警卫队的回调? 有没有人在实际生产代码中使用这些工具有经验?


它肯定会改善您的代码。您初步提出的说法是,它晦涩难懂,并且代码应从catch块中获取,这在C ++中根本不成立,因为RAII是既定的习惯用法。 C ++中的资源处理是通过资源获取来完成的,而垃圾回收是通过隐式析构函数的调用来完成的。

另一方面,显式的catch块会使代码膨胀,并引入细微的错误,因为代码流变得更加复杂,并且必须显式地进行资源处理。

RAII(包括ScopeGuard)在C ++中并不是一种晦涩的技术,但已确立了最佳实践。


是。

如果只有一条C ++代码可以建议每个C ++程序员花10分钟学习,那就是ScopeGuard(现在是可免费使用的Loki库的一部分)。

我决定尝试将ScopeGuard(稍作修改)版本用于我正在开发的小型Win32 GUI程序。您可能知道Win32具有许多不同类型的资源,需要以不同的方式关闭(例如,内核句柄通常使用CloseHandle()关闭,GDI BeginPaint()需要与EndPaint()配对等),我使用了ScopeGuard所有这些资源,还用于分配带有new的工作缓冲区(例如,用于与Unicode的字符集转换)。

令我惊讶的是程序缩短了多少。基本上,这是双赢的:您的代码同时变得更短,更健壮。将来的代码更改不会泄漏任何内容。他们只是做不到。多么酷啊?


我经常使用它来保护内存使用,这些是需要释放的东西,它们是从OS返回的。例如:

1
2
3
4
5
6
7
DATA_BLOB blobIn, blobOut;
blobIn.pbData=const_cast<BYTE*>(data);
blobIn.cbData=length;

CryptUnprotectData(&blobIn, NULL, NULL, NULL, NULL, CRYPTPROTECT_UI_FORBIDDEN, &blobOut);
Guard guardBlob=guardFn(::LocalFree, blobOut.pbData);
// do stuff with blobOut.pbData

是。

在C ++中是如此重要,以至于D中甚至是一种特殊的语法:

1
2
3
4
5
6
7
void somefunction() {
    writeln("function enter");
    // c++ has similar constructs but not in syntax level
    scope(exit) writeln("function exit");

    // do what ever you do, you never miss the function exit output
}

我认为以上答案缺少一个重要说明。正如其他人指出的那样,可以使用ScopeGuard来释放分配的资源,而不受故障(异常)的影响。但这可能不是您要使用示波器保护的唯一内容。实际上,链接文章中的示例将ScopeGuard用于不同的目的:交易。简而言之,如果您有多个对象(即使这些对象正确使用了RAII),则需要保持某种状态的关联,这可能会很有用。如果这些对象中任何一个的状态改变导致异常(我想,这通常意味着其状态没有改变),那么所有已经应用的改变都需要回滚。这就产生了它自己的一系列问题(如果回滚也失败怎么办?)。您可以尝试推出自己的类来管理此类相关对象,但是随着此类数量的增加,它会变得凌乱,并且无论如何您都可能会回到内部使用ScopeGuard


我没有使用过这个特定的模板,但是我之前使用过类似的东西。是的,与以不同方式实现的同样健壮的代码相比,它的确可以使代码更清晰。


我必须说,不,不,不是。这里的答案有助于说明为什么这是一个真正可怕的想法。资源处理应通过可重用的类完成。他们使用范围保护器实现的唯一一件事就是违反wazoo的要求,并在整个代码库中复制其资源释放代码,而不是编写一个类来处理整个资源。

如果范围警卫有任何实际用途,则资源处理不是其中之一。在这种情况下,它们比普通的RAII逊色得多,因为RAII已进行重复数据删除,并且自动保护和范围保护是手动代码复制或无效。


推荐阅读

    linux编译源代码命令?

    linux编译源代码命令?,工具,代码,百度,最新,环境,项目,系统,电脑,密码,内核,l

    linux同步代码命令?

    linux同步代码命令?,时间,系统,通信,网络,标准,图片,服务,代码,线程,单位,Lin

    linux代码对齐命令?

    linux代码对齐命令?,系统,地址,标准,信息,对比,名称,代码,命令,文件,工作,lin

    linux命令运行代码?

    linux命令运行代码?,代码,单位,系统,环境,连续,保险,工具,命令,文件,音乐,Lin

    搭建linux命令行代码?

    搭建linux命令行代码?,系统,软件,工作,名字,服务,代码,地址,环境,管理,密码,l

    linux查看命令代码?

    linux查看命令代码?,系统,信息,代码,名称,命令,设备,数字,第一,软件,管理,在L

    linux删除代码命令行?

    linux删除代码命令行?,系统,代码,命令,文件,不了,环境,档案,名称,目录,文件

    linux命令行代码实现?

    linux命令行代码实现?,标准,代码,管理,网络,地址,工作,命令,网上,环境,名称,

    linux桌面命令代码?

    linux桌面命令代码?,电脑,系统,密码,环境,代码,基础,地址,服务,网上,通讯,lin

    c代码执行linux命令?

    c代码执行linux命令?,系统,工作,标准,情况,代码,环境,设备,命令,函数,指令,li

    linux进入代码行命令?

    linux进入代码行命令?,系统,代码,设备,终端,环境,信息,第一,命令,窗口,模式,

    linux命令行看代码?

    linux命令行看代码?,代码,基础,系统,命令,数字,工作,情况,进程,程序,终端,在L

    linux命令代码怎么看?

    linux命令代码怎么看?,时间,系统,代码,命令,状态,工具,情况,电脑,实时,基础,l

    pycharm无法输入代码?

    pycharm无法输入代码?,代码,环境,工具,分析,输入法,键盘,性能,计算机,问题,

    python代码的规范建议

    python代码的规范建议,代码,异常,二元,设计,数字,下降,一致,培训,标准,空行