成员数据应该在析构函数中始终为 Cleared/Zeroed 吗?

Should Member Data Always be Cleared/Zeroed in the Destructor?

在析构函数中 clear/zero 对象的基本成员数据有什么好的理由吗?为了整洁或隐私,这似乎应该被视为标准做法,因为有可能的方法可以从已删除的对象中重新读取数据:

#include <iostream>

class Box {
    public:
        Box(int s) : secret(s), buffer(this) {}
        ~Box() {}
        /*BETTER DESTRUCTOR ~Box() {secret = 0;}*/
        void print() {std::cout << secret << std::endl;}
    private:
        void* buffer;
        int secret;
};

int main() {
    Box* carton = new Box(8675309);
    Box* crate = carton;
    delete carton;
    crate->print();
}

(请注意,buffer 只是必要的,因为没有它,某些内容会覆盖 crate->print() 之前的 secret。)

将成员数据归零是否需要“太多时间”,以至于它被认为是不值得的(特别是如果你必须遍历一个数组并将每个归零元素)?

显然这不是像 STL 容器这样更复杂的数据成员的问题,因为 their destructors clear their data, and also pointers should not be cleared 用于调试目的。

IF 你的 class 包含 "secret" 东西,然后在销毁时清除它会有助于防止它被保存在你的内存中不再拥有。但这并不意味着您可以阻止某人在您的应用程序使对象处于活动状态时拍摄内存快照,因此作为一种安全措施,它很差......

但一般来说,不,析构函数不应将 class 中的内容清零。这是浪费时间。

当然,这与 "it shouldn't remove members in dynamically allocated structures" 不同,例如 std::vector 会这样做。它会破坏向量的所有内容,因为不知道这些元素的析构函数做了什么。

一个相当不错的优化器将删除您的 secret = 0 分配。

原因很简单。最简单的优化之一是删除无效的指令。此类指令的常见 class 是写入后不进行读取。由于 this->secret=0 是析构函数中的最后一条语句,因此编译器可以轻松确定您再也不会读取 secret 了。删除指令很容易节省。

您可能想知道为什么要进行这种优化,这种情况发生的频率是多少?答案是“经常”,因为优化不是孤立发生的。例如,当调用者不检查错误代码时,内联 returns 错误代码的函数时,这种写不读的情况很常见。内联后,这是写入错误代码而没有匹配的读取。