没有编译错误的第一次机会异常
First chance exception without compiling errors
我写的代码编译没有错误,所以我不知道错误发生的原因。
#pragma once
class Macierz
{
public:
class Wiersz
{
public:
int *tab;
int dlugosc;
Wiersz(int d);
};
int x;
int y;
Wiersz *wiersze;
public:
Macierz(int m, int n);
Macierz(Macierz &m);
Macierz & operator+(Macierz &m);
Macierz & operator-(Macierz &m);
Macierz & operator*(Macierz &m);
Macierz & operator=(Macierz &m);
int& operator()(int x, int y);
string to_String();
};
#include "stdafx.h"
#include "Macierz.h"
Macierz::Macierz(int _x, int _y) :x(_x), y(_y)
{
Wiersz **tab = new Wiersz*[_x];
for (int i = 0; i < x; i++)
tab[i] = new Wiersz(_y);
wiersze = *tab;
}
Macierz::Macierz(Macierz &m) :Macierz(m.x, m.y)
{
for (int i = 0; i < x; i++)
for (int j = 0; j < y; j++)
wiersze[i].tab[j] = m.wiersze[i].tab[j];
}
Macierz & Macierz::operator+(Macierz &m)
{
if (x != m.x || y != m.y) throw "Macierze maja rozne rozmiary";
Macierz *temp = new Macierz(m);
for (int i = 0; i < x; i++)
for (int j = 0; j < y; j++)
(*temp).wiersze[i].tab[j] += wiersze[i].tab[j];
return *temp;
}
Macierz & Macierz::operator-(Macierz &m)
{
if (x != m.x || y != m.y) throw "Macierze maja rozne rozmiary";
Macierz *temp = new Macierz(m);
for (int i = 0; i < x; i++)
for (int j = 0; j < y; j++)
(*temp).wiersze[i].tab[j] -= wiersze[i].tab[j];
return *temp;
}
Macierz & Macierz::operator*(Macierz &m)
{
Macierz *temp;
if (x == m.y)
{
temp = new Macierz(m.x, y);
for (int i = 0; i < (*temp).x; i++)
for (int j = 0; j < (*temp).y; j++)
for (int l = 0; l < m.y; l++)
(*temp).wiersze[i].tab[j] += wiersze[i].tab[l] * m.wiersze[l].tab[j];
}
else if (y == m.x)
{
temp = new Macierz(x, m.y);
for (int i = 0; i < (*temp).x; i++)
for (int j = 0; j < (*temp).y; j++)
for (int l = 0; l < y; l++)
(*temp).wiersze[i].tab[j] += wiersze[i].tab[l] * m.wiersze[l].tab[j];
}
else throw "Rozmiary macierzy sie nie zgadzaja";
return *temp;
}
Macierz & Macierz::operator=(Macierz &m)
{
for (int i = 0; i < x; i++)
for (int j = 0; j < y; j++)
wiersze[i].tab[j] = m.wiersze[i].tab[j];
return *this;
}
int& Macierz::operator()(int x, int y)
{
return wiersze[x].tab[y];
}
Macierz::Wiersz::Wiersz(int i)
{
dlugosc = i;
tab = new int[dlugosc];
}
string Macierz::to_String()
{
std::ostringstream str;
str << "|";
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y; j++)
str << wiersze[j].tab[i] << ",";
str << "\b|\n";
}
return str.str();
}
在 main 中使用构造函数不会使程序崩溃:
Macierz m1(1,1);
但是访问某些数据字段似乎有问题,例如
m1(0,0) = 1;
(至少这是黄色箭头指向的代码行)
程序用于矩阵(+, -, *)的运算。我以类似的方式为欧几里得矢量运算编写了一个程序,它运行得非常好。
提前感谢您的帮助。
由于有很多指针运算,我敢打赌这是一个内存访问问题。
无论如何,当您使用 C++ 时,您应该利用矩阵 class 而不是重新发明轮子 ...
例如 Basic Linear Algebra Library with his matrix class 是顶级参考。
有了这样的class,在调试模式下编译时,会检查内存访问并帮助您快速找到错误的索引。
你的代码中有很多问题会导致问题:
- 您的构造函数
Macierz(int _x, int _y)
并不像您认为的那样工作。完成后只有 wiersze[0]
有效,任何非零索引将访问未知内存。问题实际上出在您的 2D 矩阵设计 class 上。我会摆脱手动管理的内存,只使用 2D 矢量 vector<vector<int>>
或者甚至只是平面 1D 矢量并手动管理索引。
- 您的复制构造函数
Macierz(Macierz &m)
没有为新矩阵分配内存,因此您正在写入未知内存。
- 所有二元运算符(+、-、*)分配一个新对象并 return 它会导致内存泄漏。规范的方法通常是修改对象,并且只是
return *this;
此类运算符。有关运算符重载的更多详细信息,请参阅 this question。
- 您的复制运算符
Macierz::operator=(Macierz &m)
不会检查矩阵的大小是否相同。如果大小不同,则需要销毁并重新分配矩阵。
- 您的
Macierz::operator()(int x, int y)
不检查输入索引,这可能是故意的,但您可以考虑像其他方法一样抛出异常。
- 您没有析构函数,这会导致内存泄漏,但如果您使用
vector<>
,则不需要析构函数。
如果您真的need/want从头开始实现二维矩阵class,您可以在线搜索大量现有代码,例如this one,作为操作示例.
我写的代码编译没有错误,所以我不知道错误发生的原因。
#pragma once
class Macierz
{
public:
class Wiersz
{
public:
int *tab;
int dlugosc;
Wiersz(int d);
};
int x;
int y;
Wiersz *wiersze;
public:
Macierz(int m, int n);
Macierz(Macierz &m);
Macierz & operator+(Macierz &m);
Macierz & operator-(Macierz &m);
Macierz & operator*(Macierz &m);
Macierz & operator=(Macierz &m);
int& operator()(int x, int y);
string to_String();
};
#include "stdafx.h"
#include "Macierz.h"
Macierz::Macierz(int _x, int _y) :x(_x), y(_y)
{
Wiersz **tab = new Wiersz*[_x];
for (int i = 0; i < x; i++)
tab[i] = new Wiersz(_y);
wiersze = *tab;
}
Macierz::Macierz(Macierz &m) :Macierz(m.x, m.y)
{
for (int i = 0; i < x; i++)
for (int j = 0; j < y; j++)
wiersze[i].tab[j] = m.wiersze[i].tab[j];
}
Macierz & Macierz::operator+(Macierz &m)
{
if (x != m.x || y != m.y) throw "Macierze maja rozne rozmiary";
Macierz *temp = new Macierz(m);
for (int i = 0; i < x; i++)
for (int j = 0; j < y; j++)
(*temp).wiersze[i].tab[j] += wiersze[i].tab[j];
return *temp;
}
Macierz & Macierz::operator-(Macierz &m)
{
if (x != m.x || y != m.y) throw "Macierze maja rozne rozmiary";
Macierz *temp = new Macierz(m);
for (int i = 0; i < x; i++)
for (int j = 0; j < y; j++)
(*temp).wiersze[i].tab[j] -= wiersze[i].tab[j];
return *temp;
}
Macierz & Macierz::operator*(Macierz &m)
{
Macierz *temp;
if (x == m.y)
{
temp = new Macierz(m.x, y);
for (int i = 0; i < (*temp).x; i++)
for (int j = 0; j < (*temp).y; j++)
for (int l = 0; l < m.y; l++)
(*temp).wiersze[i].tab[j] += wiersze[i].tab[l] * m.wiersze[l].tab[j];
}
else if (y == m.x)
{
temp = new Macierz(x, m.y);
for (int i = 0; i < (*temp).x; i++)
for (int j = 0; j < (*temp).y; j++)
for (int l = 0; l < y; l++)
(*temp).wiersze[i].tab[j] += wiersze[i].tab[l] * m.wiersze[l].tab[j];
}
else throw "Rozmiary macierzy sie nie zgadzaja";
return *temp;
}
Macierz & Macierz::operator=(Macierz &m)
{
for (int i = 0; i < x; i++)
for (int j = 0; j < y; j++)
wiersze[i].tab[j] = m.wiersze[i].tab[j];
return *this;
}
int& Macierz::operator()(int x, int y)
{
return wiersze[x].tab[y];
}
Macierz::Wiersz::Wiersz(int i)
{
dlugosc = i;
tab = new int[dlugosc];
}
string Macierz::to_String()
{
std::ostringstream str;
str << "|";
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y; j++)
str << wiersze[j].tab[i] << ",";
str << "\b|\n";
}
return str.str();
}
在 main 中使用构造函数不会使程序崩溃:
Macierz m1(1,1);
但是访问某些数据字段似乎有问题,例如
m1(0,0) = 1;
(至少这是黄色箭头指向的代码行)
程序用于矩阵(+, -, *)的运算。我以类似的方式为欧几里得矢量运算编写了一个程序,它运行得非常好。
提前感谢您的帮助。
由于有很多指针运算,我敢打赌这是一个内存访问问题。
无论如何,当您使用 C++ 时,您应该利用矩阵 class 而不是重新发明轮子 ...
例如 Basic Linear Algebra Library with his matrix class 是顶级参考。
有了这样的class,在调试模式下编译时,会检查内存访问并帮助您快速找到错误的索引。
你的代码中有很多问题会导致问题:
- 您的构造函数
Macierz(int _x, int _y)
并不像您认为的那样工作。完成后只有wiersze[0]
有效,任何非零索引将访问未知内存。问题实际上出在您的 2D 矩阵设计 class 上。我会摆脱手动管理的内存,只使用 2D 矢量vector<vector<int>>
或者甚至只是平面 1D 矢量并手动管理索引。 - 您的复制构造函数
Macierz(Macierz &m)
没有为新矩阵分配内存,因此您正在写入未知内存。 - 所有二元运算符(+、-、*)分配一个新对象并 return 它会导致内存泄漏。规范的方法通常是修改对象,并且只是
return *this;
此类运算符。有关运算符重载的更多详细信息,请参阅 this question。 - 您的复制运算符
Macierz::operator=(Macierz &m)
不会检查矩阵的大小是否相同。如果大小不同,则需要销毁并重新分配矩阵。 - 您的
Macierz::operator()(int x, int y)
不检查输入索引,这可能是故意的,但您可以考虑像其他方法一样抛出异常。 - 您没有析构函数,这会导致内存泄漏,但如果您使用
vector<>
,则不需要析构函数。
如果您真的need/want从头开始实现二维矩阵class,您可以在线搜索大量现有代码,例如this one,作为操作示例.