Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 动态数组删除_C++_Arrays_Destructor - Fatal编程技术网

C++ 动态数组删除

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

我正在使用动态数组,我遇到了一个问题。编译器对第一个数组(长度为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);
}

程序崩溃,因为复制
MyClass
只复制指针成员,不创建新数组,然后可以删除该数组。因此,删除同一数组两次,这是未定义的行为

如果每个实例都应该有自己的数组,那么最好的修复方法是使用原始数组,而不是使用原始数组


如果您(对于某些人为的限制,没有实际的用例)需要使用原始数组,请定义合适的复制构造函数和赋值运算符。请参阅。

该程序崩溃,因为复制
MyClass
只会复制指针成员,而不会创建新的数组,然后可以删除该数组。因此,删除同一数组两次,这是未定义的行为

如果每个实例都应该有自己的数组,那么最好的修复方法是使用原始数组,而不是使用原始数组


如果您(对于某些人为的限制,没有实际的用例)需要使用原始数组,请定义合适的复制构造函数和赋值运算符。请参阅。

为什么要复制
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;
    }
    

    仅在构建新成员后替换现有成员。这样,如果分配新实例时抛出异常,则对象仍处于其旧状态。

    为什么要复制
    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”的值。

    您需要定义您违反的复制构造函数。还可以尝试理解智能指针并使用它们