问题标签 [destructor]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
11 回答
547 浏览

c# - 强制执行所需的函数调用

我在 C# 中有一个“状态”类,使用如下:

你明白了。MyFunction 的所有调用者都应该检查返回的状态:

然而,懒惰的呼叫者可以忽略状态。

或者

有可能使这成为不可能吗?例如抛出异常

一般来说:是否可以编写一个必须调用某个函数的 C# 类?

在 Status 类的 C++ 版本中,我可以对析构函数中的一些私有 bool bIsChecked 编写测试,并在有人不检查此实例时敲响一些铃声。

C# 中的等效选项是什么?我在某处读到“你不想在你的 C# 类中使用析构函数”

IDisposable 接口的 Dispose 方法是一个选项吗?

在这种情况下,没有可释放的非托管资源。此外,还不确定GC何时释放该对象。当它最终被处置时,是否仍然可以知道您在何时何地忽略了该特定状态实例?“using”关键字确实有帮助,但同样,懒惰的调用者不需要它。

0 投票
5 回答
86181 浏览

c++ - 在 C++ 中,构造函数和析构函数可以是内联函数吗?

VC++ 生成在类声明内联函数中实现的函数。

如果我Foo如下声明一个类,那么是 CONSTRUCTOR 和 DESTRUCTOR 内联函数吗?

0 投票
4 回答
11719 浏览

vb.net - VB.NET - 实现 IDisposable 时是否应该添加 Finalize 方法?

在 Visual Studio 中,当我键入“ Implements IDisposable”行时,IDE 会自动添加:

  • 成员disposedValue变量
  • 一种Sub Dispose() Implements IDisposable.Dispose
  • 一种Sub Dispose(ByVal disposing As Boolean)

应该不理Dispose()会,清理代码应该放在Dispose(disposing).

然而Dispose Finalize Pattern说你也应该重写Sub Finalize()call Dispose(False)。为什么 IDE 也不添加这个?我必须自己添加它,还是以某种方式隐式调用它?

编辑:知道为什么 IDE 会自动添加 80% 的所需内容但忽略 Finalize 方法吗?这种功能的全部意义不在于帮助您不要忘记这些事情吗?

EDIT2:谢谢大家的出色回答,现在这很有意义!

0 投票
3 回答
341 浏览

c++ - 有没有办法确定是否发生异常?

在析构函数中,有没有办法确定当前是否正在处理异常?

0 投票
17 回答
131377 浏览

c++ - 如果你不应该在析构函数中抛出异常,你如何处理其中的错误?

大多数人说永远不要从析构函数中抛出异常——这样做会导致未定义的行为。Stroustrup 指出“向量析构函数显式调用每个元素的析构函数。这意味着如果元素析构函数抛出,向量析构失败......确实没有很好的方法来防止析构函数引发的异常,所以库不保证元素析构函数是否抛出”(来自附录 E3.2)

这篇文章似乎另有说法 - 抛出析构函数或多或少是可以的。

所以我的问题是——如果从析构函数中抛出导致未定义的行为,你如何处理析构函数期间发生的错误?

如果在清理操作过程中发生错误,您是否忽略它?如果它是一个可以在堆栈中处理但不能在析构函数中正确处理的错误,那么从析构函数中抛出异常是否有意义?

显然,这类错误很少见,但也有可能。

0 投票
8 回答
8448 浏览

c++ - RAII vs. exceptions

The more we use RAII in C++, the more we find ourselves with destructors that do non-trivial deallocation. Now, deallocation (finalization, however you want to call it) can fail, in which case exceptions are really the only way to let anybody upstairs know of our deallocation problem. But then again, throwing-destructors are a bad idea because of the possibility of exceptions being thrown during stack unwinding. std::uncaught_exception() lets you know when that happens, but not much more, so aside from letting you log a message before termination there's not much you can do, unless you're willing to leave your program in an undefined state, where some stuff is deallocated/finalized and some not.

One approach is to have no-throw destructors. But in many cases that just hides a real error. Our destructor might, for example, be closing some RAII-managed DB connections as a result of some exception being thrown, and those DB connections might fail to close. This doesn't necessarily mean we're ok with the program terminating at this point. On the other hand, logging and tracing these errors isn't really a solution for every case; otherwise we would have had no need for exceptions to begin with. With no-throw destructors we also find ourselves having to create "reset()" functions that are supposed to be called before destruction - but that just defeats the whole purpose of RAII.

Another approach is just to let the program terminate, as it's the most predictable thing you can do.

Some people suggest chaining exceptions, so that more than one error can be handled at a time. But I honestly never actually seen that done in C++ and I've no idea how to implement such a thing.

So it's either RAII or exceptions. Isn't it? I'm leaning toward no-throw destructors; mainly because it keeps things simple(r). But I really hope there's a better solution, because, as I said, the more we use RAII, the more we find ourselves using dtors that do non-trivial things.

Appendix

I'm adding links to interesting on-topic articles and discussions I've found:

0 投票
25 回答
636818 浏览

java - Java有析构函数吗?

Java有析构函数吗?我似乎无法找到任何有关此的文档。如果没有,我怎样才能达到同样的效果?

为了使我的问题更具体,我正在编写一个处理数据的应用程序,并且规范说应该有一个“重置”按钮,可以将应用程序恢复到其刚启动的原始状态。但是,除非应用程序关闭或按下重置按钮,否则所有数据都必须是“实时的”。

通常作为 C/C++ 程序员,我认为这很容易实现。(因此我计划最后实现它。)我构建了我的程序,使所有“可重置”对象都在同一个类中,这样我就可以在按下重置按钮时销毁所有“活动”对象。

我在想如果我所做的只是取消引用数据并等待垃圾收集器收集它们,如果我的用户反复输入数据并按下重置按钮,会不会出现内存泄漏?我也在想,既然 Java 作为一门语言已经相当成熟,应该有一种方法可以防止这种情况发生或优雅地解决这个问题。

0 投票
7 回答
8685 浏览

.net - 为什么 .NET 中没有 RAII?

作为一名 C++ 开发人员,Java 和 .NET 中缺少RAII(资源获取即初始化)一直困扰着我。清理的责任从类编写者转移到其消费者(通过try finally.NET 的using构造)这一事实似乎明显逊色。

我明白为什么在 Java 中不支持 RAII,因为所有对象都位于堆上,而垃圾收集器本身不支持确定性销毁,但在 .NET 中引入了值类型(struct)我们有(似乎) RAII 的完美候选人。在堆栈上创建的值类型具有明确定义的范围,并且可以使用 C++ 析构函数语义。但是,CLR 不允许值类型具有析构函数。

我的随机搜索发现了一个论点,即如果一个值类型被装箱,它就属于垃圾收集器的管辖范围,因此它的销毁变得不确定。我觉得这个论点不够有力,RAII 的好处大到足以说明带有析构函数的值类型不能被装箱(或用作类成员)。

长话短说,我的问题是:是否有任何其他原因不能使用值类型来将 RAII 引入 .NET?(或者你认为我关于 RAII 明显优势的论点有缺陷吗?)

编辑:我一定没有清楚地表达这个问题,因为前四个答案没有抓住重点。我知道它的非确定性Finalize特征,我知道using构造,我觉得这两个选项不如 RAII。using类的消费者还必须记住一件事(有多少人忘记将 aStreamReader放在一个using块中?)。我的问题是关于语言设计的哲学问题,为什么它是这样的,可以改进吗?

例如,使用通用的确定性可破坏值类型,我可以使usingandlock关键字变得多余(可通过库类实现):


我不禁以我曾经看过但目前无法找到其来源的恰当报价作为结尾。

当我冰冷的死手超出范围时,您可以承担我的确定性破坏。——匿名

0 投票
8 回答
12871 浏览

c# - 如果构造函数抛出异常,是否调用析构函数?

寻找 C# 和 C++ 的答案。(在 C# 中,将“析构函数”替换为“终结器”)

0 投票
4 回答
1948 浏览

ruby - Ruby 中的 RAII(或者,如何在 Ruby 中管理资源)

我知道这是设计使然,您无法控制对象被销毁时会发生什么。我也知道将一些类方法定义为终结器。

但是,C++ 的 RAII 的 ruby​​ 习语是(资源在构造函数中初始化,在析构函数中关闭)吗?即使发生错误或异常,人们如何管理对象内部使用的资源?

使用确保工作:

但是该类的用户必须记住每次需要调用 open 方法时 都要执行整个 begin-rescue-ensure chacha 。

例如,我将有以下课程:

如果异常是由其他类引起的并且脚本退出,则不会关闭 resource_handle。

还是更多的问题是我仍然在做这件事太像 C++?