为什么析构函数挂起

用户名

下面的代码工作正常。但是,当我启用p=&bin时GetValue,代码失败“ Debug Assertion Failed”。为什么?

class A{
int *p; 
public: 
A(){p=nullptr;}
~A(){if(p!=nullptr)delete p;}
void GetValue(int b);
};

void A::GetValue(int b){
*p=b;
//p=&b;  this will cause destructor to hang, why?
}

int main(void){
A B;
B.GetValue(5);
}
老刺猬

首先,仅delete使用分配的内存非常重要new当前,您的类A存储p未使用分配的指针new,但是您delete p好像已经这样做了。结果是未定义的行为,这意味着不能保证您的程序行为正确,并且应该预期到非常奇怪的错误。

其次,在函数中A::GetValue(int b);,参数b是一个临时变量。GetValue调用时,会在调用堆栈上留出一些空间来传递b的值,该值在函数的整个生命周期中都驻留在其中。但是GetValue返回之后那里b 不再存在尽管C ++允许您将指针存储到无效的内存中,但是您需要小心避免使用此类指针。

为了使您的课堂A正常工作,需要进行一些修饰,但我会尽力解释。虽然当前int*在一个简单的int成员将要存储的地方存储指针似乎没有多大意义,但我将继续使用该指针来帮助您理解,并让管理原始指针成为一项学习练习。


大多数问题都来自于A::GetValue(int)在这里,您将存储临时变量的地址,并且在需要new-ed指针的上下文中您应该确保正确分配内存,而不要存储指向transient参数的指针b

A::GetValue(int b){
    if (p == nullptr){
        // if p is null, it needs to be allocated before being written to
        p = new int(b); // initialize the memory at p to have value b
    } else {
        // otherwise, p has already been allocated, and its old value can be overwritten
        *p = b;
    }
}

当您编写以下代码时,还会出现另一个更细微的问题:

A a1, a2;
a1.GetValue(13);
a2 = a1;

这些行之后将发生的事情是的p成员a1将被删除两次,从而导致更多未定义的行为。罪魁祸首是自动生成的副本分配运算符,它仅按值复制pa1a2要解决此问题,您需要编写自己的副本分配运算符和副本构造函数,如下所示。复制构造函数有点复杂,因为有很多不同的情况需要处理。

class A {
    ...
    A(const A& other) : p(nullptr) {
        if (other.p){
            p = new int(*other.p); // allocate new int and initialize with other's value
        }
    }
    A& operator=(const A& other){
        if (p){
            // if this is managing a pointer
            if (other.p){
                // if other is managing a pointer too, just copy value
                *p = *other.p;
            } else {
                // otherwise, since other is null, delete and make this null
                delete p;
                p = nullptr;
            }
        } else {
            // if this is not managing a pointer
            if (other.p){
                // other is managing a pointer, time to allocate
                p = new int(*other.p);
            }
            // nothing needs to be done if both are null
        }
    }

“三定律”中解释了这样做的重要性

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章