【问题标题】:c++ destructor de-allocation issuec ++析构函数解除分配问题
【发布时间】:2013-12-14 23:42:47
【问题描述】:

我正在尝试编写一个包含双 * 数组的类,该数组可以通过各种方式填充,在程序结束时,应该释放内存 - 唉,这不起作用。

我收到“programname.exe 已触发断点”的通知,这导致我进入 main.cpp 的最后一行 - 当我删除我的析构函数时它工作正常,所以我假设它必须这样做有什么东西。

以下是相关代码:

.h

    #pragma once
using namespace std;
#include <iostream>
class polynom
{
public:
    polynom(int grad, double* arr);
    polynom(int grad);
    polynom();
    ~polynom(void);
    polynom& operator=(polynom p);
    friend ostream& operator<<(ostream& os, const polynom& p);
private:
    int grad;
    double* arr;
};

.cpp

polynom::polynom(int grad, double* arr)
{
    this->grad = grad;
    this->arr = arr;
}

polynom::polynom(int grad)
{
    this->grad = grad;
    this->arr = new double[grad];
}

polynom::polynom()
{
    arr = NULL;
}

polynom::~polynom()
{
    delete[] arr;
}

主要

void main()
{
    double arr1[] = {5,0,1};
    double arr2[] = {3,2,1};
    polynom p1 = polynom(2, arr1);
    polynom p2 = polynom(2, arr2);
    system("pause");
}

非常感谢!

【问题讨论】:

  • 您正在尝试删除堆栈分配的数组,这会使应用程序正常崩溃。您可能希望避免使用原始指针,而是查看td::shared_ptrstd::unique_ptr
  • 你不能delete内存不是从new分配的
  • 这显然不是主要问题,但不要忘记定义一个复制 c`tor。
  • What is The Rule of Three? 的可能重复项

标签: c++ destructor memory-management


【解决方案1】:

你遇到了三法则。

如果你这样做,它会起作用:

polynom p1(2, arr1);
polynom p2(2, arr2);

问题是您的赋值运算符不会复制数组,因此当您分配本地临时文件时,它会立即被销毁(与数组一起)。然后当你的本地人超出范围时,他们会尝试删除一个已经被删除的指针。

您应该创建一个复制构造函数polynom(const polynom&amp;),而不是覆盖operator=。你很少需要覆盖operator=。复制构造函数也更加通用 - 它允许您按值传递对象,而 operator= 仅特定于赋值。

无论如何,您必须分配一个新数组并复制内容,而不是复制指针。你真的应该使用std::vector,你不会有这些问题。

【讨论】:

  • 很抱歉,我不能完全理解 - 我已将代码更改为 polynom p1(2,arr1); 等,但它仍然无法正常工作。覆盖 = 运算符是我的教授给出的限制。
  • 对不起,另一个答案解决了这个问题。我没有检查你所有的构造函数。我指出了一个不同的问题。
【解决方案2】:

在下文中,您将堆栈定义的变量分配给多项式中的 arr 数组。

double arr1[] = {5,0,1};
double arr2[] = {3,2,1};
polynom p1 = polynom(2, arr1);
polynom p2 = polynom(2, arr2);

一旦多项式被破坏,它就会删除那些指针......你可能不会这样写:

double arr1[] = {1,2,3};
delete arr1;

同样的问题。

--- 更新

有两种可能的解决方案来解决这个问题:

  1. 接受用户数据的构造函数分配一个缓冲区并进行复制

这是最安全的,因为这样对象内部的缓冲区被认为是安全的。在非常大的项目中,从长远来看,这将为您节省大量时间,假设您不分配数百万个多项式对象......在这种情况下,速度可能会成为问题。

  1. 构造函数将输入标记为用户输入,这意味着它无权删除它,调用者对此负责

这通过添加一个布尔标志来工作,如果设置为 true(例如),析构函数不会删除缓冲区。

但是,这种方法存在一个大问题:如果您使用基于堆栈的缓冲区并返回多项式,则该缓冲区会被 return 语句删除并且您有一个错误...

因此我不建议你永远使用这种方法。

--- 补充说明

您写了polynom(2, arr1); ...请注意,您在数组中有三个元素。我建议您改用 sizeof():polynom(sizeof(arr1)/sizeof(arr1[0]), arr1);

另外,正如另一个答案所提到的,您希望重载多项式复制构造函数和复制赋值,否则两者都会破坏您的代码。但是,只要您不复制多项式,就可以了。但是,就目前而言,您最终会使用默认值,它们根本无法正常工作。

【讨论】:

  • 有没有办法分配堆栈定义的变量并且仍然能够设置一个“正确的”析构函数? - 这种输入数组的方法是我的教授建议的。
  • 您必须分配一个新数组并复制您传递的数组的内容。或使用std::vector
  • 啊,谢谢,我相应地更改了 2 参数构造函数,现在它可以工作了
猜你喜欢
  • 2021-06-12
  • 2010-10-28
  • 1970-01-01
  • 2013-03-02
  • 2013-03-20
  • 2017-06-22
  • 2018-09-08
  • 2013-05-23
  • 1970-01-01
相关资源
最近更新 更多