我是C ++的新手(我学过Fortran编程),我想为多维表动态分配内存。此表是私有成员变量:
class theclass{
public:
void setdim(void);
private:
std::vector < std::vector <int> > thetable;
}
我想用函数setdim()设置thetable的维度。
void theclass::setdim(void){
this->thetable.assign(1000,std::vector <int> (2000));
}
编译这个程序没问题,但是当我执行它时,我遇到了分段错误。
对我来说奇怪的是,这段代码(见下文)完全符合我的要求,除了它不使用我班级的私有成员变量:
std::vector < std::vector < int > > thetable;
thetable.assign(1000,std::vector <int> (2000));
顺便说一下,如果thetable是一维向量,我也没有问题。在课堂上:
std::vector < int > thetable;
如果在setdim中:
this->thetable.assign(1000,2);
所以我的问题是:为什么在thetable和this-&gt; 2D矢量的表格之间存在“分配”这样的差异?我该怎么做才能做我想做的事?
谢谢你的帮助,
致以最诚挚的问候,
- 弗鲁瓦
答案 0 :(得分:1)
因为它适用于本地而不是你的类变量,我的通灵调试能力告诉我你在setdim
的空或无效指针/实例上调用theclass
。
答案 1 :(得分:0)
感谢大家的意见。我正在去做一个只有有问题的部分的小源代码的路上,当我试图运行它时,它工作...我很困惑所以我试图找到指令之间的差异。最后,我发现我忘记了
#include <vector>
在其中一个源文件中(主文件,但不是具有类定义的文件)。这对我来说很奇怪,因为没有它,我不明白它是如何编译的......所以这应该是另一个问题,但我仍然不明白把这些放在哪里#include ... Fortran的生活更容易; - )
再次感谢你,
- 弗鲁瓦
答案 2 :(得分:0)
一次加载东西:
1)代码更有用,因为大多数人都忽略了实际重要的一点。因此,将您的代码转换为最简单的可编译示例,然后您可以在此处进行设置。
2)分段错误:
但是当我执行它时,我遇到了分段错误。
由于你没有指针,这个通常意味着你超越了数组的范围。从0开始访问C数组中的注释 - > (n-1)所以1000个元素的数组具有元素0 - > 999.如果你访问超出数组末尾的应用程序,应用程序不会抱怨,但你会破坏内存。
检查此转换运算符[]到.at()。
thetable[0][5] = BLA
thetable.at(0).at(5) = BLA // This tests the bounds and will
// throw an exception if you make a mistake.
3)标识符绑定到具有最近范围的变量。因此,优良作法是为您的标识符指定唯一的名称,以便它们不会发生冲突。 'thetable'指的是局部变量,而this-&gt; thetable指的是成员。它更容易给他们独特的名字。
std::vector < std::vector < int > > thetable;
thetable.assign(1000,std::vector <int> (2000));
// This is not a good idea if you have a member called thetable.
// Some people (not me) like to prefix member variables with m_ to distinguish
// them from automatic local variables.
class theclass
{
Type m_thetable;
void theMethod()
{
Type thetable;
m_thetable = thetable;
}
答案 3 :(得分:0)
虽然很多人都喜欢你的方法,但如果你想让它快速(例如,使用矩阵,你需要一块内存并自己编制索引。
这有很多原因。首先,你需要为顶层向量分配一个内存块,为每行(或列,因为你来自FORTRAN土地......)分配一个向量。
因此,您需要n + 1而不是单个操作。
这适用于每次处理此对象,复制,销毁,你有什么。 您还存储每行的向量(大小,容量)的开销。当然,如果每一行的大小不同,这就是一个特征。
因此,请考虑以下内容,为了清晰起见,硬编码加倍: 看看构造函数是多么简单,以及像+ =这样的操作有多简单,因为它可以按顺序遍历整个块,忽略索引。
通过两个数组索引单个元素的速度也较慢。计算机必须从对象访问顶级向量,找到指针,跳转并找到第二个指针。
运算符()
中提供了任意索引class Matrix {
private:
int m_rows, m_cols;
double* m_data;
public:
Matrix(int rows, int cols) : m_rows(rows), m_cols(cols), m_data(new double[rows*cols]
{}
~Matrix() { delete [] m_data; }
Matrix(const Matrix& orig) m_rows(orig.m_rows), m_cols(orig.m_cols),
m_data(new double[m_rows * m_cols]
{}
// operator = too....
Matrix& operator +=(const Matrix& right) {
assert(m_rows == right.m_rows && m_cols == right.m_cols);
for (int i = 0; i < m_rows*m_cols; i++)
m_data[i] += right.m_data[i];
}
double& operator()(int r, int c) { return m_data[r * m_cols + c]; }
double operator()(int r, int c) const { return m_data[r * m_cols + c]; }
};