C ++:动态内存分配和类构造函数

时间:2015-08-03 09:00:04

标签: c++ oop memory memory-management memory-leaks

我相信我可能要么滥用OOP,要么在类构造函数中对内存分配做错了。

我将用简化的例子说明我在做什么:

class data
{
    data(int n) : m_data(new double[n])
    {
    }

    virtual ~data()
    {
        delete [] m_data;
    }

    double min() { ... }
    double max();
    double mean(); // return minimum, maximum and mean values

    double *m_data;
}

class dual_data : public data
{
    dual_data(int n) : m_data(new double[2*n])
    {
    }
}

我相信这会导致灾难性的内存泄漏。 (应该清楚为什么,因为一个构造函数在另一个构造函数之前分配内存,然后用另一个调用new覆盖指针。)

如果还不清楚,我有两个类:一个是类似于std::vector的类,它为我处理内存中的数据存储,另一个是执行相同操作的派生类,但是期望数据的格式为x,y对而不是单个值。这样做的原因是x,y对可以用不同于矢量的方式处理。例如,使用统计数据处理来完全计算相关性或其他内容。但是,能够调用继承自min()的类max()中的函数mean()dual_datadata仍然很有用。

我该怎么做才能纠正内存泄漏?

5 个答案:

答案 0 :(得分:2)

也许这应该做:你告诉基类分配一个2 * n元素的数组。除了基类负责释放内存。不需要析构函数。

class dual_data : public data
{
    dual_data(int n) : data(2*n)
    {
    }
}

答案 1 :(得分:0)

由于data已经有一个双打数组,而不是尝试用它来捣乱,只需在dual_data中创建另一个并行数组的双精度数。

class data
{
  public:
    data(int n) : m_data(new double[n])
    {
    }

    virtual ~data()
    {
        delete [] m_data;
    }
    double *m_data;
}

class dual_data : public data
{
  public:
    dual_data(int n) : data(n), d_data(n)
    {
    }

    virtual ~dual_data() {
        delete[] d_data;
    }
    double* d_data;
}

现在,您的dual_data类具有原始m_data数组,以及相同长度的其他d_data数组,其元素将用于该对中的第二个元素。例如,第0对将是(m_data[0], d_data[0])

答案 2 :(得分:0)

您无法初始化父类的变量。它不会编译。

如果你在构造函数中进行了内存泄漏,那么你可能会发生内存泄漏。

class dual_data : public data
{
public:
    dual_data(int n) : data(n)
    {
         m_data = new double[2*n];
    }
};

然而,你的责任是做得好。一个伟大的粉末是一个很大的责任。

你做到了这一点:

class dual_data : public data
{
public:
     dual_data(int n) : data(2*n) {}
};

更好的解决方案是不使用继承。它总是更好Composititon over inheritance

#include "data.h"

class dual_data {
public:
     dual_data( int n ) : data_1(n), data_2(n) {}
private:
     data data_1;
     data data_2;
};

更好地使用接口:

class CdataIf
{
public:
     virtual ~CDataIf() = 0;
     virtual double min() = 0;
     virtual double max() = 0;
     virtual double mean() = 0;
};

class data      : public CdataIf { ... };
class data_dual : public CdataIf { ... };

答案 3 :(得分:0)

首先,实现基本向量类(如果可能,直接使用std::vector<double>

class vector_of_double
{
public:
    explicit vector_of_double(std::size_t mSize) :
        mValues(new double[size]{}),
        mSize(size)
    {}

    ~vector_of_double() { delete[] mValues; }

    // implement these if required
    // deleted for now to Respect rule of 3(5) as default implementation is incorrect.
    vector_of_double(const vector_of_double&) = delete;
    vector_of_double& operator = (const vector_of_double&) = delete;
    vector_of_double(const vector_of_double&&) = delete;
    vector_of_double& operator = (const vector_of_double&&) = delete;

    std::size_t size() const { return mSize; }

    // Implement required missing stuff if required as push_back, resize, empty, clear
    // introduction of mCapacity may be required.

    double operator[] (std::size_t index) const { return mValues[index]; }
    double& operator[] (std::size_t index) { return mValues[index]; }

    // To be able to use for range and iterator style
    const double* begin() const { return mValues; }
    const double* end() const { return mValues + mSize; }

    double* begin() { return mValues; }
    double* end() { return mValues + mSize; }

private:
    double* values;
    std::size_t size;
};

然后你可以实现你的类(不用担心内存管理):

class data
{
public:
    explicit data(int n) : m_data(n) {}

    // Or use your own implementation
    // TODO: Handle case with empty vector
    double min() const { return *std::min_element(m_data.begin(), m_data.end()); }
    double max() const { return *std::max_element(m_data.begin(), m_data.end()); }
    double mean() const {return std::accumulate(m_data.begin(), m_data.end(), 0.) / m_data.size();}

private:
    vector_of_double m_data;
};

class dual_data
{
public:
    explicit dual_data(int n) : m_data1(n), m_data2(n) {}

    // your functions as
    std::pair<double, double> means() double {return {m_data1.means(), m_data2.means()};}

private:
    data m_data1;
    data m_data2;
};

答案 4 :(得分:0)

我会采用不同的方法,而是声明一个包含min,max和mean的接口。然后创建实现接口但具有不同底层结构的类。

struct ICommon
{
  virtual double min() = 0;
  virtual double max() = 0;
  virtual double mean() = 0;
};

class Data : public ICommon
{...};

class DualData : public ICommon
{...};