我想为多维数组设计一个 C++ 类。我所说的多维是指 1d、2d、3d 等。该类支持逐元素加法和标量乘法运算符。假设 A 和 B 是该类的实例(具有相同的大小和维度)。我想在这样的表达式中使用对象:
C = A * 2 + B
我想知道的是如何管理内存。在上面的表达式中,A * 2 会创建一个类的临时对象,这个对象稍后会添加到 B 中。反正添加完成后临时对象就是垃圾。我写了下面的类,它运行良好,但我很确定它会泄漏内存。现在我的问题是,
- 如何解决内存问题?设计类(class)的最佳方式是什么?
是否可以在堆栈而不是堆上分配所需的内存?
class XArray { int num_dim; int *dims; int *index_helper; int table_size; double *table; public: XArray(const int n, const int *d):num_dim(n), dims(d) { int size = 1; for (int i = 0; i < n; i++) { size *= d[i]; } table_size = size; table = new double[size]; index_helper = new int[n]; }; ~XArray() { delete[] table; delete[] index_helper; }; int dim(int d) { return dims[d]; } double& operator()(int i) { index_helper[0] = i; return get_helper(1, index_helper); } double& operator()(int i, int j) { index_helper[0] = i; index_helper[1] = j; return get_helper(2, index_helper); } double& operator()(int i, int j, int k) { index_helper[0] = i; index_helper[1] = j; index_helper[2] = k; return get_helper(3, index_helper); } XArray operator*(double m) { XArray *xa = new XArray(num_dim, dims); for (int i = 0; i < table_size; i++) { xa->table[i] = this->table[i] * m; } return *xa; } XArray operator+(const XArray &that) { if (num_dim != that.num_dim) { char *msg = new char[100]; sprintf(msg, "XArray::dimensions do not match in + operation, expected %d, found %d", num_dim, that.num_dim); throw msg; } for (int i = 0; i < num_dim; i++) { if (this->dims[i] != that.dims[i]) { char *msg = new char[100]; sprintf(msg, "XArray::dimension %d not mached, %d != %d", i, dims[i], that.dims[i]); throw msg; } } XArray *xa = new XArray(num_dim, dims); for (int i = 0; i < table_size; i++) { xa->table[i] = this->table[i] + that.table[i]; } return *xa; } private: double& get_helper(int n, int *indices) { if (n != num_dim) { char *msg = new char[100]; sprintf(msg, "XArray::dimensions do not match, expected %d, found %d", num_dim, n); throw msg; } int multiplier = 1; int index = 0; for (int i = 0; i < n; i++) { if (indices[i] < 0 || indices[i] >= dims[i]) { char *msg = new char[100]; sprintf(msg, "XArray::index %d out of range, %d not in (0, %d)", i, indices[i], dims[i]); throw msg; } index += indices[i] * multiplier; multiplier *= dims[i]; } return table[index]; }
};
最佳答案
我想念复制构造函数和赋值运算符。您将需要这些来制作内部缓冲区的拷贝,而不仅仅是复制指针,否则您最终将释放相同的内存两次。
如果您要支持 c++0x,您可能还想实现移动语义以获得最佳性能。
像您这样抛出动态分配的对象是一个非常糟糕的主意。
在您的运算符(operator)*中,您应该在堆上创建对象:
XArray operator*(double m)
{
XArray xa(num_dim, dims);
for (int i = 0; i < table_size; i++) {
xa->table[i] = this->table[i] * m;
}
return xa;
}
但是,只要您不编写(移动)复制构造函数,这就会崩溃。因为 return 语句将制作一个拷贝,该拷贝引用与 xa 相同的内部数据。 xa 将被销毁,它的析构函数将销毁它的内部数据。因此,返回的临时对象在内部指向已销毁的数据。
编辑:
链接到关于 Move semantics or rvalue references 的信息
关于c++ - 在 C++ 中设计多维数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6606496/