Home > OS >  Replace pointer(s) with reference?
Replace pointer(s) with reference?

Time:10-20

When I needed to allocate memory through a function, most of the time I was using double pointers (when I was experiencing C). However, now I'm learning C and I was wondering if there is a way to replace double pointer with a reference (&) or something similar?

See a little example bellow!

struct Matrix {
   int** pMatrix;
   int row, column;
};

int allocate_memory(Matrix** ppMatrix) {
    // allocate memory for ppMatrix
}

int main() {
   Matrix* ptr = nullptr;
   allocate_memory(&ptr);
   return 0;
   /*
      Can we do something like this?
      Matrix obj_matrix;
      allocate_memory(obj_matrix);
      ...
   */
}

Edit: some people have been saying that I should avoid using direct allocation in my c program. The thing is I'm not allowed to use containers yet since we didn't learn them on the lesson so.. I'm basically forced to do stuff with pointers, yeah..

CodePudding user response:

Yes, in this case, you can replace the double-pointer parameter of allocate_memory() with an object reference, eg:

struct Matrix {
   int** pMatrix;
   int row, column;
};

int allocate_memory(Matrix &matrix) {
    // allocate memory for matrix.pMatrix
}

void free_memory(Matrix &matrix) {
    // free memory for matrix.pMatrix
}

int main() {
   Matrix obj_matrix;
   allocate_memory(obj_matrix);
   ...
   free_memory(obj_matrix);
   return 0;
}

Though, in this case, it would be better to define a constructor and destructor instead, eg:

struct Matrix {
   int** pMatrix;
   int row, column;

   Matrix(params...) {
      // allocate memory for pMatrix
   }

   ~Matrix() {
      // free memory for pMatrix
   }

   // also need: Matrix(const Matrix &), Matrix(Matrix&&),
   // and operator=(Matrix) to round out the Rule of 3/5/0...
};

int main() {
   Matrix obj_matrix(params...);
   ...
}

CodePudding user response:

As others have pointed out in the comments, you don't need any of this. C standard library has correctly and efficiently implemented containers.

Since you can't use them and you have to roll your own, here are some pointers:

  • Take note of single responsibility principle. The class that is responsible with memory management should only be responsible with memory management. That means you create a separate class from Matrix that is responsible with memory management and the Matrix class now doesn't care at all how memory is managed. What do you know C standard library already has such a class: std::unique_ptr. I am going to assume that you are not allowed to use that either.

  • in C almost always you implement the rule of zero. Since that is out of the window because you can't use standard classes (sigh) you need to implement the rule of three to manually manage your memory. Usually you also implement swap to make this easier.

  • usually for performance reasons a matrix is flattened. That is the underlying memory is a vector of size (n*m) and simple math is used to convert from linear indexing to matrix indexing. This makes allocation simpler so I am going to use that.

  • int is not the best data type for storing size, but then again neither is std::size_t so ... int it is for now.

Somethin like this to get you started (disclaimer: not tested nor compiled):

class VectorMemory
{
     int* data_;
     int size_;

public:
     VectorMemory(int size)
         : data_(new int[size]),
           size_(size)
     {
     }

     VectorMemory& operator=(const VectorMemory& other)
     {
          // Important note: this has no exception guarantee
          // and will leak memory on exception
          // I use this because it is simpler, but keep this in mind

          delete[] data_;
          data_ = new int[other.size_];
          size_ = other.size_;

          for (int i = 0; i < size_;   i)
              data_[i] = other.data_[i];
     }

     VectorMemory(const VectorMemory& other)
         : data_(new int[other.size_]),
           size_(other.size_)
     {
          for (int i = 0; i < size_;   i)
             data_[i] = other.data_[i];
     }

     ~VectorMemory()
     {
          delete[] data_;
     }

     int* data_() { return data_; }
     const int* data_() const { retur data_; }

     int size() const { return size_; }
};
class Matrix
{
      MatrixMemory data_;
      int n_, m_;

public:
      Matrix(int n, int m)
         : data{n * m},
           n_{n},
           m_{m}
      {
      }

      int& at(int i, j)
      {
           return data_[i * n_   j];
      }
}
  • Related