我正在使用动态数组,而且我遇到了问题。编译器为第一个数组(长度为1)调用析构函数两次。所以程序崩溃了。我很乐意得到任何帮助。谢谢。
class MyClass{
public:
int *a;
MyClass(int i){
a = new int[i];
}
~MyClass(){
if (a) delete[]a;
}
};
int main(){
MyClass c(1);
c = MyClass(2);
}
答案 0 :(得分:3)
程序崩溃,因为复制MyClass
仅复制指针成员,而不创建新数组,然后可以将其删除。因此,您删除两次相同的数组,即Undefined Behavior。
最好的解决方法是使用std::vector<int>
而不是原始数组,如果每个实例都应该有自己的数组。
如果您(为了某些人为限制,没有实际的用例)需要使用原始数组,请定义合适的复制构造函数和赋值运算符。请参阅"The rule of Three"。
答案 1 :(得分:1)
为什么要复制MyClass
实例,调用默认生成器复制构造函数。这只会复制内部a
指针,而不会创建新的int
数组。
因此,当副本被销毁时,它delete
是数组,然后当原始文件被销毁时,它也是delete
的数组。
有两种解决方法:
std::vector
(规则为0,我们将在一分钟内完成此操作),或者如果你想创建这样一个课程,比如教育兴趣,请注意,目前,无法正确编写复制构造函数/赋值运算符,因为您不会存储数组的大小,因此您不知道副本的大小应该是多少
例如,如果将数组大小存储在名为int
的{{1}}成员中,则复制构造函数可能如下所示:
i
编写复制赋值运算符有点棘手,因为您需要处理MyClass(const MyClass& rhs) : a(0), i(rhs.i) {
a = new int[i];
std::copy(rhs.a, rhs.a+rhs.i, a);
}
现有数组,甚至在重新分配新数组时还原原始状态会引发异常:
编辑:抱歉,我以前的delete
示例是完全废话,此版本更好:
operator=
您只能在构建新成员之后替换现有成员。这样,如果分配新的抛出异常,则该对象仍处于旧状态。
答案 2 :(得分:0)
这是因为同样的&#34; a&#34;被删除了两次。 发生了什么:
解决方案不是复制&#34; a&#34;的地址,而是创建一个复制构造函数并复制&#34; a&#34;的值。代替。