C++ 动态数组删除
我正在使用动态数组,我遇到了一个问题。编译器对第一个数组(长度为1)调用析构函数两次。所以程序崩溃了。我很高兴能得到任何帮助。多谢各位C++ 动态数组删除,c++,arrays,destructor,C++,Arrays,Destructor,我正在使用动态数组,我遇到了一个问题。编译器对第一个数组(长度为1)调用析构函数两次。所以程序崩溃了。我很高兴能得到任何帮助。多谢各位 class MyClass{ public: int *a; MyClass(int i){ a = new int[i]; } ~MyClass(){ if (a) delete[]a; } }; int main(){ MyClass c(1); c = MyCla
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);
}
程序崩溃,因为复制
MyClass
只复制指针成员,不创建新数组,然后可以删除该数组。因此,删除同一数组两次,这是未定义的行为
如果每个实例都应该有自己的数组,那么最好的修复方法是使用原始数组,而不是使用原始数组
如果您(对于某些人为的限制,没有实际的用例)需要使用原始数组,请定义合适的复制构造函数和赋值运算符。请参阅。该程序崩溃,因为复制
MyClass
只会复制指针成员,而不会创建新的数组,然后可以删除该数组。因此,删除同一数组两次,这是未定义的行为
如果每个实例都应该有自己的数组,那么最好的修复方法是使用原始数组,而不是使用原始数组
如果您(对于某些人为的限制,没有实际的用例)需要使用原始数组,请定义合适的复制构造函数和赋值运算符。请参阅。为什么要复制
MyClass
实例,将调用默认的生成器复制构造函数。这只是复制内部a
指针,并不创建新的int
数组
因此,当副本被销毁时,它将删除
数组,然后当原始副本被销毁时,它也将删除
数组
有两种解决方法:
i
的int
成员中,则复制构造函数可能如下所示:
MyClass(const MyClass& rhs) : a(0), i(rhs.i) {
a = new int[i];
std::copy(rhs.a, rhs.a+rhs.i, a);
}
编写拷贝分配操作符有点棘手,因为您需要处理删除现有数组,甚至在分配新数组引发异常时恢复原始状态:
编辑:对不起,我以前的操作符=
示例完全是废话,这个版本更好:
MyClass& operator=(const MyClass& rhs) {
int *newA = new int[rhs.i];
std::copy(rhs.a, rhs.a+rhs.i, newA);
i = rhs.i;
delete[] a;
a = newA;
return *this;
}
仅在构建新成员后替换现有成员。这样,如果分配新实例时抛出异常,则对象仍处于其旧状态。为什么要复制MyClass
实例,将调用默认的生成器复制构造函数。这只是复制内部a
指针,并不创建新的int
数组
因此,当副本被销毁时,它将删除
数组,然后当原始副本被销毁时,它也将删除
数组
有两种解决方法:
更可取:使用一些可以为您包装所有分配和复制的东西,例如(0规则,我们将在一分钟内讨论),或者如果您试图创建这样一个类,例如出于教育兴趣
遵循(以前是3,在C++11引入移动语义之前)。每当您有需要特殊创建/销毁的数据成员时,请确保在所有构造函数和析构函数中适当地处理它:复制/移动构造/分配和销毁
请注意,目前不可能正确地编写复制构造函数/赋值运算符,因为您不存储数组的大小,所以不知道副本应该是什么大小
例如,如果将数组大小存储在名为i
的int
成员中,则复制构造函数可能如下所示:
MyClass(const MyClass& rhs) : a(0), i(rhs.i) {
a = new int[i];
std::copy(rhs.a, rhs.a+rhs.i, a);
}
编写拷贝分配操作符有点棘手,因为您需要处理删除现有数组,甚至在分配新数组引发异常时恢复原始状态:
编辑:对不起,我以前的操作符=
示例完全是废话,这个版本更好:
MyClass& operator=(const MyClass& rhs) {
int *newA = new int[rhs.i];
std::copy(rhs.a, rhs.a+rhs.i, newA);
i = rhs.i;
delete[] a;
a = newA;
return *this;
}
仅在生成新成员后替换现有成员。这样,如果分配新的对象会引发异常,则对象仍处于旧状态。这是因为相同的“a”被删除两次。
发生了什么:
MyClass c(1)//在地址1分配了一个
MyClass(2)//在地址2分配了一个
c=…/现在c.a指向地址2,因为c只是复制右侧对象的每个成员
在2处创建的对象。被销毁,因此地址2被释放
c被破坏,因此地址2第二次被释放,导致崩溃
解决方案不是复制“a”的地址,而是创建一个复制构造函数,然后复制“a”的值。发生这种情况是因为同一个“a”被删除了两次。
发生了什么:
MyClass c(1)//在地址1分配了一个
MyClass(2)//在地址2分配了一个
c=…/现在c.a指向地址2,因为c只是复制右侧对象的每个成员
在2处创建的对象。被销毁,因此地址2被释放
c被破坏,因此地址2第二次被释放,导致崩溃
解决方案不是复制“a”的地址,而是创建一个复制构造函数,然后复制“a”的值。您需要定义您违反的复制构造函数。还可以尝试理解智能指针并使用它们