- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我对以下 C++ 代码感到困惑(在 http://cpp.sh/8bmp 在线运行它)。它结合了我在类(class)中学习的几个概念。
#include <iostream>
using namespace std;
class A {
public:
A() {cout << "A ctor" << endl;}
virtual ~A() {cout << "A dtor" << endl;}
};
class B: public A {
public:
B() {cout << "B ctor" << endl;}
~B() {cout << "B dtor" << endl;}
void foo(){cout << "foo" << endl;}
};
int main(){
B *b = new B[1];
b->~B();
b->foo();
delete b;
return 0;
}
输出:
A ctor
B ctor
B dtor
A dtor
foo
A dtor
这是我不明白的地方:
foo
?delete
?delete b;
这段代码会不会泄漏内存?A
的析构函数是虚拟的。我认为子类中重载的虚函数不会被调用。为什么 ~A()
会被调用?b->~B();
,则 B dtor
行将打印在 foo
之后。为什么?b->~B();
行两次,则输出为:B dtor\nA dtor\nA dtor
。嗯?delete B;
切换为 delete[] b;
,我会得到相同的输出。我认为第二个是正确的,因为 b
是用 new[]
创建的,但这并不重要,因为我只推送一个 B
到堆。对吗?很抱歉问了这么多问题,但这让我很困惑。如果我的个别问题被误导了,请告诉我我需要了解什么才能了解每个析构函数何时运行。
最佳答案
“未定义行为”(简称 UB)是允许编译器做任何事情的地方——这通常意味着介于“崩溃”、“给出不正确的结果”和“无论如何做你期望的事情”之间的某个地方。你的 b->foo()
绝对是未定义的,因为它发生在你的 b->~B()
调用之后,
由于您的 foo
函数实际上并没有使用任何被析构函数破坏的东西,所以对 foo
的调用“有效”,因为没有任何东西被使用被摧毁。 [这绝不是保证 - 它只是碰巧起作用,有点像有时不看就过马路是可以的,而其他时候则不然。根据道路的不同,这可能是一个非常糟糕的主意,或者在大多数情况下可能会奏效 - 但人们说“向左看,向右看,向左看,然后在安全的情况下穿过”(或类似的东西)是有原因的那个)]
在已销毁的对象上调用 delete
也是 UB,因此,它“有效”(在“不会导致程序崩溃”的意义上)再次纯属运气.
同时将 delete
与 new []
混合使用或相反也是 UB - 同样,编译器 [及其相关的运行时] 可能会做正确或错误的事情,具体取决于根据情况和条件。
不要依赖程序中的未定义行为 [1]。它一定会回来咬你。 C 和 C++ 有很多 UB 情况,至少了解最常见的情况是很好的,例如“销毁后使用”、“释放后使用”等,并注意此类情况 - 并避免不惜一切代价!
关于c++ - 我怎样才能理解这些析构函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34258299/
我开始考虑在我 future 的项目或重构中实现控制反转容器,我想知道在正确设计依赖项时哪些原则(除了 GoF 模式)可能需要牢记在心。假设我需要构建一个简单的控制台应用程序,如果它可以访问互联网,它
假设我有一个 RxC contingency table 。这意味着有 R 行和 C 列。我想要一个维度为 RC × (R + C − 2) 的矩阵 X,其中包含行的 R − 1 “主效应”以及列的
我正在尝试使用 DKMS 为正在运行的内核 (4.4) 构 build 备树覆盖。我天真的 Makefile 如下: PWD := $(shell pwd) dtbo-y += my-awsome-o
我有一个 sencha touch 项目。我是用 phonegap 2.9 构建的,并且可以正常工作 device.uuid 返回到设备 ID。当我尝试使用 3.1 device.uuid 构建时抛出
我在安装了 Xcode 4.5.1 的 Mt Lion 上运行。 默认情况下,当我构建并部署到 iOS 5.1 设备时,显示会在我旋转设备时旋转,但当我部署到 iOS 6 模拟器或运行 iOS 的 i
我正在尝试使用 Google Analytics Reporting API v4 构建多折线图。 一张图表,其中我按每天的 session 计数为每个设备(台式机/平板电脑/移动设备)设置了一条线。
我一生都无法使用 xcode 组织者“自动设备配置”中的“团队配置配置文件”在 xcode 4.0.1 中将我的应用程序构建到我的 iPad 上。 该应用程序完美地构建到模拟器,但当我构建到 iPad
我是一名优秀的程序员,十分优秀!