问题标签 [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 投票
3 回答
2944 浏览

c++ - C++ - 非指针类成员何时被销毁?

假设我有这个代码......

QMap factory_什么时候销毁?在调用析构函数之前,还是在析构函数期间?(我知道当 GraphFactory 的实例超出范围时将调用析构函数。但是非指针成员何时被销毁?)

编辑:当 factory_ map 到达析构函数时,我得到了无效的值。断点表明该值不会篡改存储在 QMap 中的值。

0 投票
7 回答
301 浏览

c++ - 复制堆栈变量时出现异常的析构函数行为

我写了一个测试来检查在堆栈变量上覆盖赋值之前是否调用了析构函数,但我找不到任何合理的结果解释......

这是我的测试(在 Visual C++ 2008 发布模式下):

如果我的假设是正确的,我希望得到“abcd”,如果错误,我期望得到“d”。相反,我得到“bcdx”。“x”根据分配给 ptr 的内存量而变化,表明它正在读取随机堆值。

我相信正在发生的事情(如果我错了,请纠正我)是每个构造函数调用都会创建一个新的堆栈值(让我们称它们为 s1、s2、s3、s4),然后分配让 s1.ptr 被 s4.ptr 覆盖. 然后 s4 在复制后立即被销毁,但 s1(带有悬空的 ptr)在离开范围时被销毁,导致 s4.ptr 的双重删除,而原始 s1.ptr 没有删除。

有什么办法可以解决不涉及使用 shared_ptrs 的这种无益行为?

编辑:将“删除”替换为“删除 []”

0 投票
4 回答
1926 浏览

c++ - 字符数组向量上的 C++ GCC 4.3.2 错误

它与此错误的问题相似

关于在 C++ 中将数组存储在 std::vector 中的问题

但出于不同的原因(见下文)。

对于以下 C++ 示例程序:

GCC 4.2.3 编译干净。GCC 4.3.2 发出以下错误:

原因显然是这一点

p>

我认为这被称为是由于不正确的数组到指针衰减。

我的问题是: 语言标准中是否有任何内容阻止在 std::vector 中存储数组?或者它只是那个特殊的 GCC 版本中的一个错误?

我相信这应该编译(即 4.2.3 是正确的)。

谢谢马丁

0 投票
4 回答
502 浏览

c++ - 关于C++内存分配和删除的问题

我遇到了一个严重的错误。当我在对象层次结构顶部的对象上调用 delete 时(希望导致其子对象的删除),我的程序退出,我得到了这个:

其次是看起来像是某种内存转储的东西。我已经搜索过这个错误,从我收集的信息来看,它似乎是在您尝试删除已删除的内存时发生的。不可能,因为我的代码中只有一个地方尝试删除。这是古怪的部分:它不会在调试模式下发生。有问题的代码:

p>

我已经注释掉了高度图析构函数中的所有内容,但仍然是这个错误。当错误发生时,

被打印。在调试模式下,我可以慢慢地单步执行代码

已打印,并且没有错误。如果我注释掉“删除高度图;” 行,永远不会发生错误。上面的析构函数是从另一个析构函数调用的(单独的类,没有虚拟析构函数或类似的东西)。高度图指针在这样的方法中是新的:

p>

这可能与返回在静态方法的堆栈空间中初始化的指针有关吗?我正确地删除了吗?关于我可以检查或做得更好的任何其他提示?

0 投票
1 回答
3222 浏览

vb6 - VB6 集合删除不会触发 Class_Terminate

我提前道歉;这是一个很长的问题。我已经尽可能地简化了,但它仍然比我想看到的要冗长一些。

在一些遗留代码中,我们有一个 VB6 集合。此集合通过 .Add 方法添加对象并通过 .Remove 方法删除它们。但是,通过跟踪我可以看到,有时当调用 .Remove 时,似乎没有调用对象的类终止。但这并不一致;它很少发生,我无法隔离它未能触发类终止的情况。

考虑以下演示代码:

这是测试工具代码:

现在,对于每次运行,Servant 的 class_terminate 总是被调用。而且我在生产代码中看不到任何应该保留引用集合中的对象的内容。

1.) 有什么方法可以强制类在 Remove 上终止?也就是说,我可以调用 Obj.Class_Terminate 并确保它每次都能正常工作吗?

2.)在我的生产代码(和我的小测试应用程序)上,这些类被标记为“Instancing - 5 MultiUse”。我意识到这可能是某种线程问题;有没有一种有效的方法来证明(或反驳)多线程是这个问题的原因——我可能会添加某种跟踪或我可能执行的某种其他类型的测试?


编辑:根据 MarkJ 在下面的富有洞察力的评论,我应该补充一点,上面发布的测试和生产代码都是 ActiveX exe 的——我询问多线程的部分原因。

0 投票
5 回答
3731 浏览

c++ - C++ 堆栈分配对象,显式析构函数调用

在处理现有库时,我遇到了析构函数的奇怪用法。当可能需要再次使用该对象时,显式调用了堆栈分配的 stl 向量的析构函数。这些向量对象是 stl 向量类的稍微定制的版本,具有专门的clear方法。在析构函数体中存在两个方法调用:clear(), _Tidy().

我一直在想一个很好的理由,为什么要调用这个析构函数,而不仅仅是,clear但我不知所措。任何人都可以解释为什么这可能是一个好主意?

0 投票
9 回答
7779 浏览

c++ - 为什么 STL 容器没有虚拟析构函数?

有谁知道为什么 STL 容器没有虚拟析构函数?

据我所知,唯一的好处是:

  • 它通过一个指针(指向虚拟方法表)减少实例的大小,并且
  • 它使破坏和建造速度更快。

缺点是以通常的方式对容器进行子类化是不安全的。

编辑: 也许我的问题可以改写为“为什么不设计 STL 容器以允许继承?”

因为它们不支持继承,所以当一个人想要一个需要 STL 功能和少量附加功能的新容器(比如一个专门的构造函数或具有地图默认值的新访问器,管他呢):

  • 组合和接口复制:创建一个新的模板或类,它拥有 STL 容器作为私有成员,并且每个 STL 方法都有一个直通内联方法。这与继承一样高效,避免了虚拟方法表的成本(在重要的情况下)。不幸的是,STL 容器具有相当广泛的接口,因此这需要很多行代码来完成看似容易做到的事情。
  • 只需制作函数:使用裸(可能是模板化的)文件范围函数,而不是尝试添加成员函数。在某些方面,这可能是一个很好的方法,但封装的好处却丢失了。
  • 具有公共 STL 访问权限的组合:让 STL 容器的所有者让用户访问 STL 容器本身(可能通过访问器进行保护)。这需要对库编写器进行最少的编码,但对用户来说不太方便。组合的一大卖点是减少了代码中的耦合,但此解决方案将 STL 容器与所有者容器完全耦合(因为所有者返回一个真正的 STL 容器)。
  • 编译时多态性:编写起来可能有些棘手,需要一些代码练习,并且不适用于所有情况。

作为一个附带问题:是否有一种使用非虚拟析构函数进行子类化的标准安全方式(假设我不想覆盖任何方法,只是想添加新方法)?我的印象是,如果没有能力更改定义非虚拟类的代码,就没有通用且安全的方法来执行此操作。

编辑2:

正如@doc 指出的那样,C++ 11更高级的using声明在一定程度上降低了组合成本。

0 投票
4 回答
6851 浏览

c++ - “'<' 标记之前的预期构造函数、析构函数或类型转换”

我遇到了语法/解析错误,但我似乎找不到它。

DataReader.h:11: 错误: '<' 标记之前的预期构造函数、析构函数或类型转换

这是 DataReader.h:

这是 .cpp 文件:

我跳过了 DataReader() 的内容,因为我认为它无关紧要,但如果需要,我可以发布它。

感谢您的任何意见/建议。

0 投票
9 回答
3071 浏览

c++ - 如何检查析构函数中是否已释放内存?

我有一个使用 allegro 开源库的简单坦克战争风格游戏。在我的坦克类中,我将指向位图对象的指针数组初始化为 0。然后我使用 allegro 函数 create_bitmap 创建新对象,该函数分配内存并对其进行初始化。

然后我照常做我的事情。

问题是,当我像一个好的 OO 男孩一样去释放类析构函数中的位图内存时,我使程序崩溃,因为在这个特定的程序中,快板库在类之前进行了清理(释放了它创建的位图对象)超出范围并被销毁。它不会再次将我的指针设置为 NULL,所以我无法检查位图是否仍然有效,如果我尝试释放它们,它们会使程序崩溃。

有没有办法解决?如果它们不为 NULL,我可以检查有效的指针吗?如果在程序中以不同的方式使用该类,我如何确定内存已被释放。就目前而言,我本质上是在没有删除的情况下调用 new 并且我不喜欢它。

0 投票
6 回答
2836 浏览

c++ - 在信号处理程序中显式调用析构函数

我有一个析构函数,它执行一些必要的清理(它会杀死进程)。即使将 SIGINT 发送到程序,它也需要运行。我的代码目前看起来像:

这可行,但似乎有很多警告不要显式调用析构函数。在这种情况下这是正确的做法,还是有“更正确”的方法?