矢量动态内存分配的私有成员向量

时间:2011-03-16 15:05:37

标签: c++ class vector dynamic-memory-allocation

我是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矢量的表格之间存在“分配”这样的差异?我该怎么做才能做我想做的事?

谢谢你的帮助,

致以最诚挚的问候,

- 弗鲁瓦

4 个答案:

答案 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]; }
};