动态内存分配和类构造函数
C++: Dynamic memory allocation and class constructors
我相信我可能是误用了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
的调用覆盖指针。)
如果还不清楚,我有2个类:一个是类似于std::vector
的类,它为我处理内存中的数据存储,另一个是派生类,它做同样的事情,但期望数据以x,y对的格式而不是单个值。这样做的原因是,x,y对可以用不同的方式来处理,而不仅仅是一个向量。例如,通过统计数据处理来计算相关性或其他完全不同的东西。但是可以调用dual_data
类中继承自data
的min()
、max()
和mean()
函数,这是很有用的。
我应该做什么来纠正内存泄漏?
也许应该这样做:你告诉基类分配一个2*n个元素的数组。此外,基类负责释放内存。不需要析构函数
class dual_data : public data
{
dual_data(int n) : data(2*n)
{
}
}
由于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])
。
不能初始化父类的变量。不能编译
如果在构造函数中这样做,可能会导致内存泄漏。
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) {}
};
一个更好的解决方案是不使用继承。组合总是比继承好。
#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 { ... };
首先,实现一个基本的向量类(或者如果可能的话直接使用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;
};
我将以不同的方式处理这个问题,而是声明一个包含最小,最大和平均值的接口。然后创建实现接口但具有不同底层结构的类。
struct ICommon
{
virtual double min() = 0;
virtual double max() = 0;
virtual double mean() = 0;
};
class Data : public ICommon
{...};
class DualData : public ICommon
{...};
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 具有自定义构造函数 (C++) 的类型的动态数组分配
- C 字符串在显式构造函数中分配值C++?
- 如何为 std::vector 分配内存,然后稍后为某些元素调用构造函数?
- 在构造函数中分配内存失败是如何冒泡的
- 当我尝试通过构造函数分配 char 数组时出现错误
- 如何使用函数(而不是构造函数)将派生类对象分配给基类指针
- 当设置对象等于另一个函数的返回值时,为什么要调用移动构造函数/分配
- 如何安全地释放构造函数分配的资源
- 是否可以在基类中删除复制和移动构造函数/分配运算符
- 如何在隐式复制构造函数/分配运算符中压制成员
- 使用超载构造函数分配
- 使用构造函数分配内存
- 如何使用复杂构造函数分配对象
- 将类构造函数分配给具有参数的新构造函数C++
- 在构造函数分配后更改vtable内存
- 在尝试使用 new 和 copy 构造函数分配内存时,在 '(' 令牌之前获取"预期的非限定 id"
- 为存储库构造函数分配内存
- 由c++中的双默认构造函数分配的值
- 将派生类构造函数分配给基类指针