【问题标题】:Private member vector of vector dynamic memory allocation向量动态内存分配的私有成员向量
【发布时间】:2011-07-16 16:21:57
【问题描述】:

我是 C++ 新手(我学习了 Fortran 编程),我想为多维表动态分配内存。该表是私有成员变量:

class theclass{
public:
  void setdim(void);
private:
  std::vector < std::vector <int> > thetable;
}

我想用 setdim() 函数设置表格的尺寸。

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));

顺便说一句,如果表格是一维向量,我没有问题。在课堂上:

std::vector < int > thetable;

如果在 setdim 中:

this->thetable.assign(1000,2);

所以我的问题是:为什么 2D 向量的 thetable 和 this->thetable 之间的“分配”有如此大的差异?我应该怎么做才能做我想做的事?

感谢您的帮助,

最好的问候,

-- 杰弗里

【问题讨论】:

  • 错误肯定在其他地方。你能告诉我们这个类是如何使用的,以及它的复制构造函数和析构函数是什么样的吗?
  • 如果您遇到分段错误,您是否查看了回溯以了解发生了什么?
  • 如果你在调试器中,显示'this'的值——它可能是错误的。
  • 我相信,vector&lt;vector&lt;int&gt; &gt; 不是二维数组的好选择。尽量考虑使用std::valarrayBoost.uBLAS
  • 我非常同意奥列格的观点。我看到你所做的一个主要问题是 (&thetable[1][0] - &thetable[0][1999]) 不是 1。

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


【解决方案1】:

由于它适用于本地变量,而不适用于您的类变量,我的心理调试能力告诉我,您在 theclass 的空或无效指针/实例上调用 setdim

【讨论】:

    【解决方案2】:

    感谢大家的 cmets。我正在做一个只有有问题的部分的小源代码,当我尝试运行它时,它工作了......我很困惑,所以我试图找出指令之间的差异。最后,我发现我忘记了一个

    #include <vector>
    

    在源文件之一中(主要文件,但不是具有类定义的文件)。这对我来说很奇怪,因为没有它,我不明白它如何编译......所以这应该是另一个问题,但我仍然不明白将这些#include 放在哪里...... Fortran 让生活更轻松;-)

    再次感谢您,

    -- 杰弗里

    【讨论】:

      【解决方案3】:

      一次只做一件事情:

      1) 代码作为解释更有用,因为大多数人忽略了真正重要的部分。因此,将您的代码转换为最简单的可编译示例,然后将其放在这里。

      2) 分段错误:

      但是当我执行它时,我遇到了分段错误。

      由于你没有指针,这通常意味着你已经超出了数组的边界。请注意,在 C 中,数组是从 0 -> (n-1) 访问的,因此 1000 个元素的数组具有元素 0 -> 999。如果您访问超出数组末尾的应用程序不会抱怨,但您会损坏内存。

      检查这个将 operator[] 转换为 .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->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;
           }
      

      【讨论】:

        【解决方案4】:

        虽然很多人喜欢您的方法,但如果您希望它快速(例如,对于矩阵,您需要一块内存并自己索引它。

        造成这种情况的原因有很多。首先,您需要为顶层向量分配一个内存块,并为每一行(或每列,因为您来自 FORTRAN 土地......)分配一个向量

        因此,您有 n+1,而不是单个操作。

        这适用于你每次处理这个对象,复制,销毁,你有什么。 您还为每一行存储向量的开销(大小、容量)。当然,如果每一行的大小不同,这就是一个特征。

        因此,为了清楚起见,请考虑以下硬编码为 double 的内容: 看看构造函数有多简单,像 += 这样的操作有多简单,因为它可以顺序遍历整个块,忽略索引。

        通过两个数组索引单个元素也更慢。计算机必须从对象访问顶层向量,找到一个指针,跳转到那里并找到第二个指针。

        在操作符()中提供任意索引

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-06-16
          • 2015-05-17
          • 1970-01-01
          • 2020-06-15
          • 1970-01-01
          • 2017-03-16
          • 1970-01-01
          • 2021-05-05
          相关资源
          最近更新 更多