|
|
1
273
不,C++不支持“最后”块。原因是C++支持了RAII:“资源获取是初始化” 一个非常有用的概念。 其思想是对象的析构函数负责释放资源。当对象具有自动存储持续时间时,当创建它的块退出时(即使该块在出现异常时退出),也将调用该对象的析构函数。这是 Bjarne Stroustrup's explanation RAII的一个常见用法是锁定互斥锁:
因为你指出了这一点。) .NET deterministic destruction using IDisposable and 'using' statements . 实际上,这两种方法非常相似。主要的区别在于RAII将决定性地释放任何类型的资源——包括内存。在.NET中实现IDISPosiabl(甚至.NET语言C++/CLI),除了内存之外,资源将被确定性释放。在.NET中,内存不是确定释放的;内存只在垃圾回收周期期间释放。
有人认为,“破坏就是资源的让渡”是一个更准确的说法。 |
|
|
2
79
在C++中,最后是
因为RAII需要。
RAII将异常安全的责任从对象的用户转移到对象的设计者(和实现者)。我认为这是正确的地方,因为您只需要(在设计/实现中)纠正一次异常安全。通过使用finally,您需要在每次使用对象时更正异常安全性。 同样,IMO的代码看起来更整洁(见下文)。
数据库对象。要确保使用数据库连接,必须打开和关闭它。通过使用RAII,这可以在构造函数/析构函数中完成。 C++类RAII
RAII的使用使得正确使用DB对象变得非常容易。无论我们如何尝试和滥用,DB对象都将使用析构函数正确地关闭自己。
当最终使用时,对象的正确使用被委托给对象的用户。 即 对象用户有责任正确地显式关闭数据库连接。现在您可以争辩说,这可以在finalizer中完成,但是资源可能具有有限的可用性或其他限制,因此您通常希望控制对象的释放,而不是依赖于垃圾收集器的非确定性行为。
这也是一个简单的例子。
以下是更详细的分析: http://accu.org/index.php/journals/236 |
|
|
3
63
C++中的语义使用少量代码。 这里有一个链接到 GSL Microsoft implementation 和一个链接到 Martin Moene implementation 比亚恩·斯特劳斯特罗普多次表示,GSL中的所有内容最终都将符合标准。所以这应该是一种经得起未来考验的方法 .
在C++ 11中,RAII和LAMBDAS允许最后做出一个总体:
输出为:
个人来说,我用了这几次来确保在C++程序中关闭POSIX文件描述符。 拥有一个真正的类来管理资源,从而避免任何类型的泄漏通常更好,但是 最后 在使类听起来像是过度杀戮的情况下非常有用。 最后 因为如果自然使用的话,你可以在开始代码附近写结束代码(在我的例子中 新的 删除 和C++一样,在LIFO命令中构造的破坏也一样。唯一的缺点是你得到了一个你没有真正使用的自动变量,并且lambda语法使得它有点嘈杂(在我的例子中,在第四行中只有单词 最后 另一个例子:
使残废 最后 只有在失败的情况下才能调用。例如,必须在三个不同的容器中复制对象,可以设置 最后 撤消每个副本并在所有副本成功后禁用。这样做,如果破坏不能扔,你保证有力的保证。 使残废
如果你不能使用C++ 11,你仍然可以拥有 ,但代码变得有点冗长。只需定义一个只有构造函数和析构函数的结构,构造函数就可以引用所需的任何内容,析构函数就可以执行所需的操作。这基本上就是lambda所做的,手动完成的。
|
|
|
4
32
除了使基于堆栈的对象易于清理之外,RAII也很有用,因为当对象是另一个类的成员时,会发生相同的“自动”清理。当拥有的类被销毁时,RAII类所管理的资源将被清理,因为该类的dtor将因此被调用。
|
|
|
5
30
实际上,基于垃圾收集器的语言需要“最终”更多。垃圾收集器不会及时销毁您的对象,因此不能依赖它来正确地清理与内存无关的问题。 就动态分配的数据而言,许多人认为应该使用智能指针。
那么 |
|
|
6
9
用C++ 11λ函数实现另一种“最后”块仿真
希望编译器能优化上面的代码。 现在我们可以这样编写代码:
如果您愿意,可以将此习惯用法包装为“try-finally”宏:
现在“最后”块在C++ 11中可用:
您可以在这里测试上面的代码: http://coliru.stacked-crooked.com/a/1d88f64cb27b3813
如果你需要 最后 屏蔽你的代码,然后 scoped guards 或 ON_FINALLY/ON_EXCEPTION 下面是在最后/ON-u异常上使用的简短示例:
|
|
|
7
7
很抱歉挖出这么一条老线索,但以下推理有重大错误: 通常,您必须处理动态分配的对象、对象的动态数量等。在try块中,一些代码可能会创建许多对象(多少在运行时确定),并将指向这些对象的指针存储在列表中。现在,这不是一个异国情调,但非常普遍。在这种情况下,你会想写一些像
当然,当超出范围时,列表本身将被销毁,但这不会清理您创建的临时对象。
另外:为什么即使是托管的lanuages也会提供finally块,尽管垃圾收集器会自动释放资源? 提示:除了内存释放,“finally”还有更多的功能。 |
|
|
8
6
FWWW,微软Visual C++支持测试,最后它在MFC应用程序中被用作一种捕捉严重异常的方法,否则会导致崩溃。例如;
我以前用过这个来做一些事情,比如在退出之前保存打开文件的备份。但是,某些JIT调试设置会破坏这种机制。 |
|
|
9
6
因此,不仅C++支持
GSL实现的示例用法如下:
GSL的实现和用法与
Paolo.Bolzoni's answer
|
|
|
10
3
不完全是这样,但您可以在某种程度上模仿它们,例如:
请注意,finally块本身可能在重新引发原始异常之前引发异常,从而丢弃原始异常。这与Java finally块中的行为完全相同。而且,你不能使用
|
|
11
3
警告 :一个 earlier version 首先,让我们定义一个helper类。
可以这样使用:
警告:
有一些事情不太像java版本的
总而言之,我不知道我自己是否会用这些东西,但玩起来很有趣。:) |
|
|
12
2
如果C++支持它,您希望代码看起来像这样:
我认为将finally声明放在循环的开头更符合逻辑,因为它发生在循环退出之后。。。但这是一厢情愿的想法,因为我们不能用C++来做。注意队列
以下是您使用它的方法:
|
|
|
13
1
正如很多人所说的,解决方案是使用C++ 11的特性来避免最后的块。其中一个特点是
使用C++标准库容器的使用UNIQUYPPTR的更多介绍 here |
|
|
14
0
如果希望始终调用finally块,只需将其放在最后一个catch块之后(可能应该是
如果希望在引发任何异常时最后执行finally block,可以使用布尔局部变量-在运行之前,将其设置为false,并将true赋值放在try block的最末尾,然后在catch block检查变量值之后:
|
|
|
15
0
我还认为,RIIA并不是一个完全有用的异常处理替代品,也不是一个最终的替代品。顺便说一句,我也认为瑞亚是个坏名字。我把这类课程称为“看门人”,并经常使用。95%的情况下,他们既不初始化也不获取资源,而是在限定范围的基础上应用一些更改,或者获取已设置的内容并确保其被销毁。这是一个官方的模式名称痴迷的互联网,我被滥用,甚至认为我的名字可能更好。 我只是不认为有理由要求每一个复杂的特殊列表设置都必须有一个类来包含它,以避免在处理过程中出现错误时需要捕获多个异常类型而在清理时出现复杂情况。这将导致很多不需要的特别类。 是的,对于设计用于管理特定资源的类或设计用于处理一组类似资源的泛型类来说,这是很好的。但是,即使所有涉及的东西都有这样的包装器,清理的协调可能不仅仅是一个简单的析构函数的反向调用。 我认为C++有一个完美的意义。我的意思是,天哪,在过去的几十年里,有那么多零碎的东西被粘在上面,以至于奇怪的人会突然变得保守起来,像finally这样的东西可能会非常有用,而且可能不会像其他一些已经添加的东西那么复杂(尽管这只是我的猜测) |
|
|
16
-2
|