当我运行下面的代码时,它崩溃了。如果我删除析构函数,它就可以工作了。为什么?
#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;
}
字符串
2条答案
按热度按时间brc7rcf01#
当我运行时它崩溃了。如果我删除析构函数,它就能工作了。为什么会这样?
您的
operator +
在此处创建left
的 * 副本 *:字符串
因为你没有显式定义复制构造函数,编译器将隐式生成一个执行 * 成员方式 * 复制的构造函数。
a
数据成员的沉闷副本意味着a
指针最终将指向vectmy
的两个不同示例(result
和left
)的 * 相同 * 位置,这两个示例在销毁时都将delete[]
它。这样的双重删除会给你的程序带来undefined behavior,在你的例子中,它会表现为崩溃。
这就是Rule of Three的要点:* 每当你有一个用户定义的复制构造函数,赋值操作符,或析构函数时,你应该定义所有。
原因是,通常要定义其中一个函数,因为要管理某些资源(在本例中是内存),并且通常要在复制、析构或分配管理资源的对象时执行适当的操作。
在这个特殊的例子中,缺少一个正确的复制构造函数。你可以这样定义它:
型
另外,我建议您尽可能避免通过原始指针、
new
和delete
(或它们的数组对应项)进行手动内存管理,并考虑使用std::vector
。更新:
还要注意的是,
operator +
接受了它的参数 by value,这意味着每个参数都将被 * 复制 *(即,复制构造函数将被调用)。由于这里不需要复制,您可能希望通过引用(到
const
)获取参数:型
mbjcgjjk2#
在你的
operator+
中,字符串
这将调用默认的构造函数 * 和 * 复制构造函数,而你没有。因此将使用编译器的变体,它不会为
a
成员分配内存。对于自动生成的复制构造函数,指针将被简单地复制,使两个对象使用同一个指针。当一个删除它时,另一个指针将无效。你应该读一下the rule of three。