对象的析构函数导致崩溃

问题描述 投票:0回答:2

当我运行下面的代码时,它崩溃了。如果我删除析构函数,它就会起作用。为什么?

#include <iostream>

#include <stdlib.h>

#include <stdarg.h>

using namespace std;

class vectmy {
    public: int size;
    int * a;
    vectmy(int n, int val);
    ~vectmy() {
        delete[] a; //IF I DELETE THIS PROGRAM WORKS
    }
    vectmy & operator = (const vectmy & );
};

vectmy::vectmy(int n, int val) {
    size = n;
    a = new int[n + 1];
    for (int i = 0; i < n; ++i) {
        *(a + i) = val;
    }
}

vectmy & vectmy::operator = (const vectmy & param) {
    for (int i = 0; i < 3; ++i) a[i] = param.a[i];
    return * this;
}

vectmy operator + (vectmy left, vectmy right) {
    vectmy result = left;
    for (int i = 0; i < 3; ++i) result.a[i] = result.a[i] + right.a[i];

    return result;
}

int main() {
    int b1[3] = {
        1,
        2,
        4
    };
    vectmy d(3, 2), b(3, 4), c(3, 0);

    c = (b + d);

    for (int j = 0; j < 3; ++j) cout << c.a[j] << ' ' << endl;
    return 0;
}
c++ class crash destructor
2个回答
4
投票

当我运行时它崩溃了。如果我删除析构函数,它就会起作用。为什么会这样?

您的

operator +
在此处创建 left
副本

vectmy result = left;

由于您没有显式定义复制构造函数,编译器将隐式生成一个执行成员明智复制的复制构造函数。

a
数据成员的无意义副本意味着
a
指针最终将指向vectmy的两个不同实例(
result
left
)的
相同
位置,两者都
delete[]
销毁后。

这种双重删除会给你的程序带来未定义的行为,在你的情况下表现为崩溃。

这是三法则的要点:每次有用户定义的复制构造函数、赋值运算符或析构函数时,您可能应该定义它们的全部

原因是,您通常会定义这些函数之一,因为您正在管理某些资源(在您的情况下是内存),并且您通常希望在复制、销毁或分配管理资源的对象时执行正确的操作。

在这种特殊情况下,缺少适当的复制构造函数。您可以这样定义它:

vectmy::vectmy(vectmy const& v) { size=v.size; a = new int[size]; *this = v; }

此外,我建议您尽可能避免通过原始指针、

new

delete
(或它们的数组对应项)进行手动内存管理,并考虑使用
std::vector
来代替。

更新:

另请注意,您的

operator +

正在按值
接受其参数,这意味着每个参数都将被复制(即,将调用复制构造函数)。 由于这里并不需要副本,因此您可能希望通过引用获取参数(参见

const

):


vectmy operator + ( vectmy const& left, vectmy const& right) // ^^^^^^ ^^^^^^



1
投票
operator+

你做


vectmy result = left;

这将调用默认构造函数

复制构造函数,而您没有这些构造函数。因此将使用编译器变体,它不会为 a 成员分配内存。对于自动生成的复制构造函数,将简单地复制指针,使两个对象使用相同的指针。当一个删除它时,另一个指针就失效了。


您应该阅读

三法则

© www.soinside.com 2019 - 2024. All rights reserved.