简体   繁体   中英

Private member vector of vector dynamic memory allocation

I'm new to C++ (I learned programming with Fortran), and I would like to allocate dynamically the memory for a multidimensional table. This table is a private member variable :

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

I would like to set the dimension of thetable with the function setdim().

void theclass::setdim(void){
  this->thetable.assign(1000,std::vector <int> (2000));
}

I have no problem compiling this program, but as I execute it, I've got a segmentation fault.

The strange thing for me is that this piece (see under) of code does exactly what I want, except that it doesn't uses the private member variable of my class :

std::vector < std::vector < int > > thetable;
thetable.assign(1000,std::vector <int> (2000));

By the way, I have no trouble if thetable is a 1D vector. In theclass :

std::vector < int > thetable;

and if in setdim :

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

So my question is : why is there such a difference with "assign" between thetable and this->thetable for a 2D vector? And how should I do to do what I want?

Thank-you for your help,

Best regards,

-- Geoffroy

由于它与当地的,而不是你的类变量工作我的心灵调试力量告诉我你叫setdim上的一个空或无效的指针/实例theclass

Thank you everybody for your comments. I was on the way to do a small source code with only the problematic part, and as I tried to run it, it worked... I was very confused so I tried to find the differences between the instructions. Finally, I figured out that I forgot a

#include <vector>

in one of the source file (the main one, but not the one with the class definition). This is strange to me because without it, I don't understand how it can compile... So this should be an other question, but I still don't understand where to put these #include... Life was easier with Fortran ;-)

Thank you again,

-- Geoffroy

Ont thing at a time:

1) Code is more useful the an explanation as most people leave out the actually important bit. So convert your code into the simplest compilable example you can then posit it here.

2) A segmentation fault:

but as I execute it, I've got a segmentation fault.

Since you have no pointers, this usually means that you have stepped beyond the bounds of the array. Note in C arrays are accessed from 0 -> (n-1) so an array of 1000 elements has elements 0 -> 999. If you access beyond the end of the array the application will not complain but you will corrupt memory.

To check for this convert operator[] into .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) identifiers bind to the variable with the closest scope. Thus it is good practice to give your identifiers unique names so that they do not clash. 'thetable' refers to the local variable while this->thetable refers to the member. Its easier to give them unique names.

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

While a lot of people like your approach, if you want it to be fast (as, for example, with a matrix, you want a single block of memory and index it yourself.

There are a number of reasons for this. First, you need to allocate a single block of memory for the top level vector, and one vector for each row (or column, since you're from FORTRAN land....)

So instead of a single operation, you have n+1.

That applies every time you process this object, copying, destroying, what have you. You are also storing the overhead of the vector (size, capacity) for every row. Of course, if every row is a different size, this is a feature.

So, consider the following, hardcoded to double for clarity: Look how simple the constructor is, and how simple an operation like += is, since it can just walk through the entire block sequentially, ignoring indexing.

It's also slower to index an individual element through the two arrays. The computer has to access the top level vector from the object, find a pointer, jump there and find a second pointer.

Arbitrary indexing is provided in the operator ()

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM