所以我想创建一个4x4矩阵类,将其数据存储为float** m
。我像这样初始化它:
Matrix4f::Matrix4f()
{
this->m = new float*[4];
for (int i = 0; i < 4; i++)
{
this->m[i] = new float[4];
memset(this->m[i], 0, sizeof(float) * 4);
}
}
在那之后,我有一个析构函数,像这样:
Matrix4f::~Matrix4f()
{
for (int i = 0; i < 4; i++)
{
delete[] m[i];
}
delete[] m;
}
但是有时当我使用此类时,此行:
delete[] m[i];
导致断点,并引发:Critical error detected c0000374
这是初始化和删除4x4矩阵的正确方法吗?
如前所述,这三个规则可能是问题。您提供的代码在技术上是正确的,但是,如果您复制Matrix4f,则必须重新实现复制构造函数和重载的赋值构造函数:
#include <iostream>
class Matrix4f
{
public:
Matrix4f()
: m_data(new float*[4])
{
for (int i = 0; i < 4; i++)
m_data[i] = new float[4]{ 0 };
}
Matrix4f(const Matrix4f& source)
{
m_data = new float*[4];
for (int i = 0; i < 4; i++)
{
m_data[i] = new float[4]{ 0 };
for (int j = 0; j < 4; j++)
{
m_data[i][j] = source.m_data[i][j];
}
}
}
Matrix4f& operator=(const Matrix4f& source)
{
if (this == &source) return *this;
clear();
m_data = new float*[4];
for (int i = 0; i < 4; i++)
{
m_data[i] = new float[4]{ 0 };
for (int j = 0; j < 4; j++)
{
m_data[i][j] = source.m_data[i][j];
}
}
return *this;
}
~Matrix4f()
{
clear();
}
//private:
float**m_data;
void clear()
{
if (m_data != NULL)
{
for (int i = 0; i < 4; i++)
{
delete[] m_data[i];
}
delete[]m_data;
}
}
void print()const
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
std::cout << m_data[i][j] << "\t";
}
std::cout << "\n";
}
}
};
int main()
{
Matrix4f m1;
m1.m_data[0][0] = m1.m_data[1][1] = m1.m_data[2][2] = m1.m_data[3][3] = 1;
{
Matrix4f m2(m1);
Matrix4f m3 = m2;
m2.print();
m3.print();
}
m1.print();
}
但是我建议您改用一维向量,它更快,更安全。
如注释中所指出的,当且仅当您正确管理副本的情况时,您的代码才是好的。
您有三个选择:
让我们讨论这个选择:
您只需要声明复制构造函数和复制分配操作符即可。现在无法复制您的类的对象。这降低了矩阵类的有用性。
这本身没有任何实际价值。由于您可以通过将类型3的对象包装到std::shared_ptr
中来实现此目的。
在这种情况下,不需要动态内存。即使有,您也想使用std :: vector或其他方法来管理内存。合理的解决方案是使用float[4][4]
作为m
。因为您避免了内存管理,所以这将更加健壮。