在类的函数中使用析构函数来重置值是否可行?

3
在我的讲座中,我没有看到有人使用析构函数将值重置为其起始参数,而是在函数中手动处理每个变量。在类函数中使用析构函数进行重置/删除是否会引起任何问题?
以下是我所说的一个小例子:
    class Test1{
        private:
            int *test;
            bool valid;
        public:
        Test1(int value,bool valid=false){
            test=new int(value); this->valid=valid;
        }
        ~Test1(){
            delete test; test=nullptr; valid=false;
        }

    void ResetStats(int NewValue){
        this->~Test1();
        test1=new int(NewValue);
        valid=false;
    }

    }

new int(NewValue) 抛出 std::bad_alloc 异常。调用 ResetStats 的代码捕获了它。但是不知何故,对象已经无法使用了,即使他们可以恢复。 - StoryTeller - Unslander Monica
2
在我的讲座中,我没有看到任何人使用析构函数将值重置为其起始参数,因为这不是析构函数的作用,而是构造函数的作用。 - user2100815
2
是的,人们不这样做是因为这是一个可怕的想法,会使您的程序100% UB。给定的代码无法编译,并且即使在语法上修复后,语义上也将完全破坏。该提议从根本上误解了析构函数的目的和对象生命周期的本质。 - underscore_d
2
我很好奇为什么你会使用int* test1;而不是只用int test1;。似乎存储总是在内部处理的。即使有使用指针的好理由,你也应该优先选择std::unique_ptr<int>作为拥有指针。 - François Andrieux
@François Andrieux 我的考试使用这种格式。我知道unique_ptr更好,但我不能在我的考试中使用它们... - Adin Sijamija
2个回答

5

显式调用非平凡析构函数会结束对象的生命周期(为什么?)。

通过将功能放在单独的私有函数中,在ResetStats和析构函数之间共享功能:

// Both destructor and ResetStats call Reset
~Test1(){
    Reset(nullptr);
}
void ResetStats(int NewValue) {
    Reset(new int(NewValue));
}
// Shared functionality goes here
private Reset(int *ptr) {
    delete test;
    test=ptr;
    valid=false;
}

1

析构函数是在对象被销毁时调用的,而不是在尝试重置其状态时调用的。

为了重置值,我更喜欢使用与默认构造的对象进行交换、使用默认构造的对象进行复制/移动构造或将其移动分配给默认构造的对象。

Test1 test;
// Do stuff
test.swap(Test());

当然,你需要实现一个swap方法,一个拷贝构造函数或赋值操作符。请查阅移动语义以正确地实现它们。
考虑强制执行RAII的类。在我们的例子中,test在其构造函数中获取一个文件句柄。如果你调用析构函数来重置值,则当你尝试重置它时,对象将不再具有文件句柄,因为它是在构造函数中获取并在析构函数中释放的。
在我看来,析构函数应该只在对象被销毁时才被调用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接