I'm working on a project that requires many dynamically sized 2D arrays that need to be accessible across functions.
The code I'm working on uses pointers like double** dynArray for this.
R = ...; // ROWS of the matrix, unknown prior to runtime
C = ...; // COLUMNS of the matrix, unknown prior to runtime
double** dynArray;
After checking the existing code I found that the arrays are currently always being initialized like this:
double** dynArray = new double*[R];
for(int r=0; r<R; r++){dynArray[r] = new double[C];}
In order to improve the readability I would like to write a method to do the above.
Here's what I came up with to allocate
void initialize2D(double*** data, int R, int C){
(*dynArray) = new double*[R];
for(int r=0; r<R; r++){
(*dynArray)[r] = new double[C];
for(int c=0; c<C; c++){
(*dynArray)[r][c] = 0;
}
}
}
and free memory respectively:
void free2D(double*** data, int R, int C){
for(int r=0; r<R; r++){
delete[] (*data)[r];
}
delete *data;
}
I intended to use these methods like this:
R = ...; // ROWS of the matrix, unknown prior to runtime
C = ...; // COLUMNS of the matrix, unknown prior to runtime
double** dynArray;
initialize2D(&dynArray, R, C);
/* do stuff*/
free2D(&dynArray,R,C);
After implementing these functions I ran Valgrind and found that this qualifies as a
definitely lost, sometimes
possibly lost.
What is the problem, and what would be the proper way to initialize through a function by reference?
Write the functions the following way
double ** initialize2D( int R, int C )
{
double **dynArray = new double *[R];
for ( int r = 0; r < R; r++ )
{
dynArray[r] = new double[C]();
}
return dynArray;
}
void free2D( double **data, int R )
{
for ( int r = 0; r < R; r++ ) delete [] data[r];
delete [] data;
}
And call the functions the following way
double** dynArray = initialize2D( R, C );
/* do stuff*/
free2D( dynArray, R );
dynArray = nullptr;
Take into account that you could use standard container std::vector<std::vector<double>> instead of dynamically allocate the arrays yourself.
Assuming it is necessary to pass the pointer to the function to initialise it ...
void initialize2D(double*** data, int R, int C)
{
*data = new double*[R];
for(int r=0; r<R; r++)
{
(*data)[r] = new double[C];
for(int c=0; c<C; c++)
{
(*data)[r][c] = 0;
}
}
}
void free2D( double ***data, int R )
{
for ( int r = 0; r < R; r++ ) delete [] (*data)[r];
delete [] (*data);
*data = nullptr;
}
Personally, however, I wouldn't directly use dynamic memory allocation at all. Instead I'd do;
#include <vector>
// and in your code
void some_function()
{
std::vector<std::vector<double> > dynArray(R, std::vector<double>(C));
// use dynArray as if it is a 2D array. All elements dynArray[i][j]
// will be initialised to zero, for i = 0 to R-1 and j = 0 to C-1
dynArray[3][4] = 42; // assuming R > 3 and C > 4
// ALL memory allocated for dynArray will be released here automatically as it passes out of scope
}
The advantage of this is that the standard vector class will happily manage all memory allocation and deallocation for you.
It is easy enough to pass such vectors around by reference.
An alltogether better way to code what you have above is:
#include <vector>
std::vector<std::vector<double>> initialise2D(int r, int c)
{
std::vector<std::vector<double>> result(r);
for(int i=0; i<r; ++i) result[i].reserve(c);
return result;
}
void free2D(std::vector<std::vector<double>> &v)
{
v.clear();
}
you can then
auto dynArray = initialise3D(20, 30);
You should also note that you do not actually need free2D any longer. I kept it here only for you to see how much easier things have became.
You will also note that you can use vector in the same way as you used array. That is why there was no problem for me to write result[i] using square brackets, as if it were an array.
Related
I am trying to build some .cpp code, in an XCode project. I have a very simple function that converts a matrix of data type cv::Mat (from opencv), to a simple two-dimensional c++ array.
The function looks something like this:
int* myClass::convertMatrix(cv::Mat cvmat){
int r = cvmat.rows;
int c = cvmat.cols;
int newmat[r][c];
for(int i=0; i<r; i++){
for(int j=0; j<c; j++){
newmat[i][j] = cvmat.at<int>(i, j);
}
}
return newmat;
}
I can't figure out what's wrong. I know "lvalue" refers to a specific memory location, but what does this have to do with me returning a matrix?
You're trying to return a pointer to a temporary variable inside that function.
After the function is being returned, that variable is automatically being cleaned up by the compiler.
Also, you are trying to create a stack-allocated array with parameters that are unknown at compile-time, if you had the size of the array at compile-time, you could have marked r and c as constexpr, if it didn't complain about that consider reading about VLA.
To fix those issues, just allocate the array on the heap:
int** make_2d_array(int r, int c)
{
int** arr = new int*[r];
for(int i = 0; i < r; i++)
arr[i] = new int[c];
return arr;
}
int** myClass::convertMatrix(cv::Mat cvmat){
int r = cvmat.rows;
int c = cvmat.cols;
int** newmat = make_2d_array(r, c);
for(int i=0; i<r; i++){
for(int j=0; j<c; j++){
newmat[i][j] = cvmat.at<int>(i, j);
}
}
return newmat;
}
Don't forget to delete the array when you stopped using it.
I also recommend considering using std::vector for that, so you don't have to worry about deleting the array ( way simpler ):
std::vector<std::vector<int>> newmat(r, std::vector<int>(c));
I am trying to write a class where it starts with a small array to put values in. My objective is if the number of values exceed the capacity, the array expands to fit the remaining values. For example, if I had 5 numbers, the array would expand to accommodate the fifth value.
The object actually creates an array at run time. So when I wrote the function to expand, its actually creating a new array and pointing to it.
Heres the class
class DVec // self expanding array
{
private:
//[0...n-1] are the values, [0..cap-1] exist
int n;
double* a;
int cap;
void expand(double*);
public:
DVec(); // constructs an empty DVec
void add(double v); //adds v to the end of this DVec
int size();
double pop(); // removes and returns the last value (pre: not-empty)
double get(int idx); // returns value at idx in this DVec
void set(double v, int idx); // sets this DVec at idx to be v
};
Constructor
DVec::DVec()
{
cap = 4;
a = new double[cap];
n = 0;
}
Heres the code that I'm testing it with
void DVec::add(double v)
{
a[n++] = v;
if (n == cap) { expand(a); }
}
void DVec::expand(double*)
{
double* temp = new double[n*2];
for (int i = 0; i < n; i++)
{
temp[i] = a[i];
}
*a = *temp;
}
int main()
{
DVec a; DVec* p = new DVec();
for (int i = 0; i < 6; i++)
{
a.add(i * i);
}
cout << a.get(5);
}
My problem is that it keeps bombing out if I set the for loop to i<6. Anything lower its fine.
It comes back say it threw exception:
if (!has_cctor)
cexit();
My questions is what is this? Is it because I made a pointer equal a pointer(a* = *temp)? Or am I not even in the same galaxy as the correct way to write the function?
Edit:
Thanks for all the help guys. I made changes and it all works now.
{
double* temp = new double[cap++];
for (int i = 0; i < n; i++)
{
temp[i] = a[i];
}
a = temp;
}
DVec::DVec()
{
cap = 0;
a = new double[cap];
n = 0;
}
void DVec::add(double v)
{
if (n >= cap) { expand(a); }
a[n++] = v;
}
This line looks like the problem:
*a = *temp;
I assume you meant to replace a with temp, but what you've written is equivalent to this:
a[0] = temp[0]
You should write this instead:
a = temp;
You also need to remember to delete a before overwriting it, otherwise you will have a memory leak, as well as to update cap, or you will have further problems.
I assume you are doing this as an academic exercise rather than as a solution to a real-world problem. If not, you should use std::vector, as the standard library implementers have already done all the hard work for you.
I am trying to shrink an array of *bool but I am not sure if it is being deleted correctly.
This is my source code...
bool *oldStore;
void shrinkArray(int i)
{
int k;
bool *newStore;
for(k=0; k<i; k++)
{
newStore[k] = oldStore[k];
}
for(; k<originalSize; k++)
{
delete[] oldStore[k];
}
delete[] oldStore;
oldStore = newStore;
}
For example, if I wanted to shrink the array to 5 and the original size of the array was 15, it would keep the first five and delete the last ten, however I am not too sure if my memory is being managed correctly.
Think about you method design before going into the coding specifics. I assume you have an ínt array that you new somewhere in your code.
Think about who "owns" this array? It's probably no good idea to create the int array at some place and to simply delete[] it somewhere else. Check out the following links: What is a smart pointer and when should I use one?
Think about what should happen to your newStore array. Is it supposed to replace the oldStore or do you want both arrays to exist in parallel. If you simply put the newStore on the heap who/when and where are you going to delete[] it again.
Simplest code would be:-
void shrinkArray(int i)
{
int k;
bool *newStore = new bool[i];
for(k=0; k<i; k++)
{
newStore[k] = oldStore[k];
}
delete [] oldStore; //assuming oldstore was allocated using new []..
oldStore = newStore;
}
Your code is wrong. You declared pointer newStore but neither initialize it nor allocated memory that would be pointed to by this pointer
bool *newStore;
So the next loop has undefined behaviour.
for(k=0; k<i; k++)
{
newStore[k] = oldStore[k];
}
Moreover if each element of the array pointed to by pointer oldStore has type bool * that is in turn is a pointer then oldStore itself shall have type bool **
If so then the correct function could look like
void shrinkArray( int n )
{
if ( n < originalSize )
{
bool **newStore = new bool * [n];
int i = 0;
for ( ; i < n; i++ ) newStore[i] = oldStore[i];
for ( ; i < originalSize; i++ ) delete oldStore[i];
delete [] oldStore;
oldStore = newStore;
originalSize = n;
}
}
Take into account that oldStore also shall have type bool **.
Otherwise if each element of the original array has type bool then the code will look like
void shrinkArray( int n )
{
if ( n < originalSize )
{
bool *newStore = new bool [n];
int i = 0;
for ( ; i < n; i++ ) newStore[i] = oldStore[i];
// Or
// std::copy( oldStore, oldStore + n, newStore );
delete [] oldStore;
oldStore = newStore;
originalSize = n;
}
}
Take into account that it would be much better and simpler to use standard container std::vector<bool *> or std::vector<bool> depending on the type of the element of the container.
How do you dynamically allocate a 2D matrix in C++?
I have tried based on what I already know:
#include <iostream>
int main(){
int rows;
int cols;
int * arr;
arr = new int[rows][cols];
}
It works for one parameter, but now for two. What should I do?
A matrix is actually can be represented as an array of arrays.
int rows = ..., cols = ...;
int** matrix = new int*[rows];
for (int i = 0; i < rows; ++i)
matrix[i] = new int[cols];
Of course, to delete the matrix, you should do the following:
for (int i = 0; i < rows; ++i)
delete [] matrix[i];
delete [] matrix;
I have just figured out another possibility:
int rows = ..., cols = ...;
int** matrix = new int*[rows];
if (rows)
{
matrix[0] = new int[rows * cols];
for (int i = 1; i < rows; ++i)
matrix[i] = matrix[0] + i * cols;
}
Freeing this array is easier:
if (rows) delete [] matrix[0];
delete [] matrix;
This solution has the advantage of allocating a single big block of memory for all the elements, instead of several little chunks. The first solution I posted is a better example of the arrays of arrays concept, though.
You can also use std::vectors for achieving this:
using: 'std::vector< std::vector >'
Example:
#include <vector>
std::vector< std::vector<int> > a;
//m * n is the size of the matrix
int m = 2, n = 4;
//Grow rows by m
a.resize(m);
for(int i = 0 ; i < m ; ++i)
{
//Grow Columns by n
a[i].resize(n);
}
//Now you have matrix m*n with default values
//you can use the Matrix, now
a[1][0]=1;
a[1][1]=2;
a[1][2]=3;
a[1][3]=4;
//OR
for(i = 0 ; i < m ; ++i)
{
for(int j = 0 ; j < n ; ++j)
{ //modify matrix
int x = a[i][j];
}
}
Try boost::multi_array
#include <boost/multi_array.hpp>
int main(){
int rows;
int cols;
boost::multi_array<int, 2> arr(boost::extents[rows][cols] ;
}
arr = new int[cols*rows];
If you either don't mind syntax
arr[row * cols + col] = Aij;
or use operator[] overaloading somewhere. This may be more cache-friendly than array of arrays, or may be not, more probably you shouldn't care about it. I just want to point out that a) array of arrays is not only solution, b) some operations are more easier to implement if matrix located in one block of memory. E.g.
for(int i=0;i < rows*cols;++i)
matrix[i]=someOtherMatrix[i];
one line shorter than
for(int r=0;i < rows;++r)
for(int c=0;i < cols;++s)
matrix[r][c]=someOtherMatrix[r][c];
though adding rows to such matrix is more painful
const int nRows = 20;
const int nCols = 10;
int (*name)[nCols] = new int[nRows][nCols];
std::memset(name, 0, sizeof(int) * nRows * nCols); //row major contiguous memory
name[0][0] = 1; //first element
name[nRows-1][nCols-1] = 1; //last element
delete[] name;
#include <iostream>
int main(){
int rows=4;
int cols=4;
int **arr;
arr = new int*[rows];
for(int i=0;i<rows;i++){
arr[i]=new int[cols];
}
// statements
for(int i=0;i<rows;i++){
delete []arr[i];
}
delete []arr;
return 0;
}
or you can just allocate a 1D array but reference elements in a 2D fashion:
to address row 2, column 3 (top left corner is row 0, column 0):
arr[2 * MATRIX_WIDTH + 3]
where MATRIX_WIDTH is the number of elements in a row.
Here is the most clear & intuitive way i know to allocate a dynamic 2d array in C++. Templated in this example covers all cases.
template<typename T> T** matrixAllocate(int rows, int cols, T **M)
{
M = new T*[rows];
for (int i = 0; i < rows; i++){
M[i] = new T[cols];
}
return M;
}
...
int main()
{
...
int** M1 = matrixAllocate<int>(rows, cols, M1);
double** M2 = matrixAllocate(rows, cols, M2);
...
}
The other answer describing arrays of arrays are correct.
BUT if you are planning of doing a anything mathematical with the arrays - or need something special like sparse matrices you should look at one of the many maths libs like TNT before re-inventing too many wheels
I have this grid class that can be used as a simple matrix if you don't need any mathematical operators.
/**
* Represents a grid of values.
* Indices are zero-based.
*/
template<class T>
class GenericGrid
{
public:
GenericGrid(size_t numRows, size_t numColumns);
GenericGrid(size_t numRows, size_t numColumns, const T & inInitialValue);
const T & get(size_t row, size_t col) const;
T & get(size_t row, size_t col);
void set(size_t row, size_t col, const T & inT);
size_t numRows() const;
size_t numColumns() const;
private:
size_t mNumRows;
size_t mNumColumns;
std::vector<T> mData;
};
template<class T>
GenericGrid<T>::GenericGrid(size_t numRows, size_t numColumns):
mNumRows(numRows),
mNumColumns(numColumns)
{
mData.resize(numRows*numColumns);
}
template<class T>
GenericGrid<T>::GenericGrid(size_t numRows, size_t numColumns, const T & inInitialValue):
mNumRows(numRows),
mNumColumns(numColumns)
{
mData.resize(numRows*numColumns, inInitialValue);
}
template<class T>
const T & GenericGrid<T>::get(size_t rowIdx, size_t colIdx) const
{
return mData[rowIdx*mNumColumns + colIdx];
}
template<class T>
T & GenericGrid<T>::get(size_t rowIdx, size_t colIdx)
{
return mData[rowIdx*mNumColumns + colIdx];
}
template<class T>
void GenericGrid<T>::set(size_t rowIdx, size_t colIdx, const T & inT)
{
mData[rowIdx*mNumColumns + colIdx] = inT;
}
template<class T>
size_t GenericGrid<T>::numRows() const
{
return mNumRows;
}
template<class T>
size_t GenericGrid<T>::numColumns() const
{
return mNumColumns;
}
Using the double-pointer is by far the best compromise between execution speed/optimisation and legibility. Using a single array to store matrix' contents is actually what a double-pointer does.
I have successfully used the following templated creator function (yes, I know I use old C-style pointer referencing, but it does make code more clear on the calling side with regards to changing parameters - something I like about pointers which is not possible with references. You will see what I mean):
///
/// Matrix Allocator Utility
/// #param pppArray Pointer to the double-pointer where the matrix should be allocated.
/// #param iRows Number of rows.
/// #param iColumns Number of columns.
/// #return Successful allocation returns true, else false.
template <typename T>
bool NewMatrix(T*** pppArray,
size_t iRows,
size_t iColumns)
{
bool l_bResult = false;
if (pppArray != 0) // Test if pointer holds a valid address.
{ // I prefer using the shorter 0 in stead of NULL.
if (!((*pppArray) != 0)) // Test if the first element is currently unassigned.
{ // The "double-not" evaluates a little quicker in general.
// Allocate and assign pointer array.
(*pppArray) = new T* [iRows];
if ((*pppArray) != 0) // Test if pointer-array allocation was successful.
{
// Allocate and assign common data storage array.
(*pppArray)[0] = new T [iRows * iColumns];
if ((*pppArray)[0] != 0) // Test if data array allocation was successful.
{
// Using pointer arithmetic requires the least overhead. There is no
// expensive repeated multiplication involved and very little additional
// memory is used for temporary variables.
T** l_ppRow = (*pppArray);
T* l_pRowFirstElement = l_ppRow[0];
for (size_t l_iRow = 1; l_iRow < iRows; l_iRow++)
{
l_ppRow++;
l_pRowFirstElement += iColumns;
l_ppRow[0] = l_pRowFirstElement;
}
l_bResult = true;
}
}
}
}
}
To de-allocate the memory created using the abovementioned utility, one simply has to de-allocate in reverse.
///
/// Matrix De-Allocator Utility
/// #param pppArray Pointer to the double-pointer where the matrix should be de-allocated.
/// #return Successful de-allocation returns true, else false.
template <typename T>
bool DeleteMatrix(T*** pppArray)
{
bool l_bResult = false;
if (pppArray != 0) // Test if pointer holds a valid address.
{
if ((*pppArray) != 0) // Test if pointer array was assigned.
{
if ((*pppArray)[0] != 0) // Test if data array was assigned.
{
// De-allocate common storage array.
delete [] (*pppArray)[0];
}
}
// De-allocate pointer array.
delete [] (*pppArray);
(*pppArray) = 0;
l_bResult = true;
}
}
}
To use these abovementioned template functions is then very easy (e.g.):
.
.
.
double l_ppMatrix = 0;
NewMatrix(&l_ppMatrix, 3, 3); // Create a 3 x 3 Matrix and store it in l_ppMatrix.
.
.
.
DeleteMatrix(&l_ppMatrix);
In C++ I'd like to do something like:
int n = get_int_from_user();
char* matrix = new char[n][n];
matrix[0][0] = 'c';
//...
matrix[n][n] = 'a';
delete [][] matrix;
but of course this doesn't work. What is the best way to do something similar? I've seen some solutions to this but they seem pretty messy.
The manual dynamic way:
Let's say you want an array of width*height, the most efficient way is to just use a single dimensional array:
char *matrix = new char[width*height];
To delete it:
delete[] matrix;
To access it:
char getArrayValue(char *matrix, int row, int col)
{
return matrix[row + col*width];
}
To modify it:
void setArrayValue(char *matrix, int row, int col, char val)
{
matrix[row + col*width] = val;
}
Boost Matrix:
Consider using boost::matrix if you can have the dependency.
You could then tie into the boost linear algebra libraries.
Here is some sample code of boost::matrix:
#include <boost/numeric/ublas/matrix.hpp>
using namespace boost::numeric::ublas;
matrix<char> m (3, 3);
for (unsigned i = 0; i < m.size1 (); ++ i)
for (unsigned j = 0; j < m.size2 (); ++ j)
m (i, j) = 3 * i + j;
On the stack for some compilers:
Some compilers actually allow you to create arrays on the stack with runtime determined sizes. g++ is an example of such a compiler. You cannot do this by default VC++ though.
So in g++ this is valid code:
int width = 10;
int height = 10;
int matrix[width][height];
Drew Hall mentioned that this C99 feature is called Variable Length Arrays (VLAs) and it can probably be turned on in any modern compiler.
I usually do something like this:
char *matrix = new char [width * height];
matrix[i + j * width] = 'c'; // same as matrix[i][j] = 'c';
delete [] matrix;
You seem to be missing the whole point of C++ (C with classes) :-). This is the sort of use that's crying out for a class to implement it.
You could just use STL or other 3rd party class library which I'm sure would have the data structure you're looking for but, if you need to roll your own, just create a class with the following properties.
constructor which, given n, will just create a new n*n array of char (e.g., charray)..
member functions which get and set values based on x.y which simply refer to charray[x*n+y];
destructor which delete[]'s the array.
What about std::vector< std::vector<int> > array2d; ?
For a true two dimensional array:
int n = get_int_from_user();
char** matrix = new char*[n];
for (int i = 0; i < n; i++) {
matrix[i] = new char[n];
}
// Operations on matrix.
for (int i = 0; i < n; i++) {
delete [] matrix[i];
}
delete matrix;
Just off the top of my head. Mistakes, no doubt. However, other people have posted a more elegant approach, I think.
I like the 1-d array approach (the selected answer by Brian R. Bondy) with the extension that you wrap the data members into a class so that you don't need to keep track of the width separately:
class Matrix
{
int width;
int height;
char* data;
public:
Matrix();
Matrix(int width, int height);
~Matrix();
char getArrayValue(int row, int col);
void setArrayValue(int row, int col, char val);
}
The implementation is an exercise for the reader. ;)
I think this would be a good one.
int n = get_int_from_user();
char **matrix=new (char*)[n];
for(int i=0;i<n;i++)
matrix[i]=new char[n];
matrix[0][0] = 'c';
//...
matrix[n][n] = 'a';
for(int i=0;i<n;i++)
delete []matrix;
delete []matrix;
std::vector<int> m;
Then call m.resize() at runtime.
int* matrix = new int[w*h];
if you want to do something like Gaussian elimination your matrix should be
int** matrix = new int*[h];
for(size_t i(0); i < h; ++i)
matrix[i] = new int[w];
(in Gaussian elimination we usually need to exchange one row with another so it's better to swap pointers to rows in constant time rather than swapping by copying in linear time).