Dynamic Memory Allocation: What is the alternative for a two dimensional array when the rightmost dimension is variable? - c++

I am trying to develop a class to backup & restore console screen buffers. Here's my code in progress.
class CBuff
{
private:
CONST WCHAR max_unit;
HANDLE hnd;
CHAR_INFO *stor_buff;
COORD s_buff_sz;
COORD d_buff_cod;
SMALL_RECT read_region;
public:
CBuff():max_unit(10)
{}
~CBuff(){}
void Initiate(HANDLE hndl, SHORT buff_x, SHORT buff_y, SHORT buff_width, SHORT buff_height)
{
hnd=hndl;
stor_buff=new CHAR_INFO[buff_width*buff_height]();
s_buff_sz.X=buff_width;
s_buff_sz.Y=buff_height;
d_buff_cod.X=0;
d_buff_cod.Y=0;
read_region.Left=0;
read_region.Top=0;
read_region.Right=buff_width-1;
read_region.Bottom=buff_height-1;
}
int Backup()
{
if(!ReadConsoleOutput(hnd,stor_buff,s_buff_sz,d_buff_cod,&read_region)) return -1;
return 0;
}
int Restore()
{
if(!WriteConsoleOutput(hnd,stor_buff,s_buff_sz,d_buff_cod,&read_region)) return -1;
return 0;
}
int Backup_mp()
{/*incomplete*/}
int Restore_mp()
{/*incomplete*/}
};
It works with Backup() & Restore() fine. And then I tried to make another version of Backup, Backup_mp(handle, backup_num), that will create multiple backups from different console buffer instances. I planned on converting last four variables in private space into array, so that a index value (backup_num) can be used for different backup point. An allocation like this
stor_buff=new CHAR_INFO[index][buff_width*buff_height]();
is not working.
What option do I have?
Also, can I use CONST WCHAR max_unit as the parameter for an array like s_buff_sz[max_unit] ?

You're using C++, so make use of it: Use std::vector.
//Declaration of your buffers:
std::vector< std::vector<CHAR_INFO> > store_buffers;
//Append a new buffer entry:
store_buffers.push_back( std::vector<CHAR_INFO>( buff_width * buff_height ) );
// Pass buffer with index index to WinAPI functions:
..., store_buffers[index].data(), s_buff_sz, ...
If using C++11, you can use std::array for the fixed sized dimension (instead of std::vector, which is variable), but that's not critical.

To allocate a two-dimensional array in heap (using new), you need to allocate the pointers first, and then the arrays. Example:
stor_buff = new CHAR_INFO* [buff_height]; // Allocate rows (pointers
for(int index = 0; index < buff_height; ++index)
stor_buff[index] = new CHAR_INFO[buff_width];
And use them directly, as if store_buff is 2D array. For deallocation, you need to delete the arrays (i.e. individual rows) first, and then the row-pointer.
for(int index = 0; index < buff_height; ++index)
delete []stor_buff[index]; // NOTICE the syntax
delete []stor_buff;
Or, you may have a single-dimensional array, use it as 2D. For this you need to do (row,col) calculation to get the desired element.
You may also use vector (or vector of vector), to get the same. But I suggest you to play with native pointers, unless you get accustomed with pointers!

Related

Helper function to construct 2D arrays

Am I breaking C++ coding conventions writing a helper function which allocates a 2D array outside main()? Because my application calls for many N-dimensional arrays I want to ensure the same process is followed. A prototype which demonstrates what I am doing :
#include <iostream>
// my helper function which allocates the memory for a 2D int array, then returns its pointer.
// the final version will be templated so I can return arrays of any primitive type.
int** make2DArray(int dim1, int dim2)
{
int** out = new int* [dim1];
for (int i = 0; i < dim2; i++) { out[i] = new int[dim2];}
return out;
}
//helper function to deallocate the 2D array.
void destroy2DArray(int** name, int dim1, int dim2)
{
for (int i = 0; i < dim2; i++) { delete[] name[i]; }
delete[] name;
return;
}
int main()
{
int** test = make2DArray(2,2); //makes a 2x2 array and stores its pointer in test.
//set the values to show setting works
test[0][0] = 5;
test[0][1] = 2;
test[1][0] = 1;
test[1][1] = -5;
// print the array values to show accessing works
printf("array test is test[0][0] = %d, test[0][1] = %d, test[1][0] = %d, test[1][1] = %d",
test[0][0],test[0][1],test[1][0],test[1][1]);
//deallocate the memory held by test
destroy2DArray(test,2,2);
return 0;
}
My concern is this may not be memory-safe, since it appears I am allocating memory outside of the function in which it is used (potential out-of-scope error). I can read and write to the array when I am making a single small array, but am worried when I scale this up and there are many operations going on the code might access and alter these values.
I may be able to sidestep these issues by making an array class which includes these functions as members, but I am curious about this as an edge case of C++ style and scoping.
There is a difference between allocating 2D arrays like this and what you get when you declare a local variable like int ary[10][10] that based on your statement
My concern is that this operation may not be memory-safe, since it
appears that I am allocating memory for an array outside of the
function in which it is used (potential out-of-scope error)
I am guessing you do not fully understand.
You are allocating arrays on the heap. Declaring a local variable like int ary[10][10] places it on the stack. It is the latter case where you need to worry about not referencing that memory outside of its scope-based lifetime; that is, it is the following that is totally wrong:
//DON'T DO THIS.
template<size_t M, size_t N>
int* make2DArray( ) {
int ary[M][N];
return reinterpret_cast<int*>(ary);
}
int main()
{
auto foo = make2DArray<10, 10>();
}
because ary is local to the function and when the stack frame created by the call to make2DArray<10,10> goes away the pointer the function returns will be dangling.
Heap allocation is a different story. It outlives the scope in which it was created. It lasts until it is deleted.
But anyway, as others have said in comments, your code looks like C not C++. Prefer an std::vector<std::vector<int>> rather than rolling your own.
If you must use an array and are allergic to std::vector, create the 2d array (matrix) as one contiguous area in memory:
int * matrix = new int [dim1 * dim2];
If you want to set the values to zero:
std::fill(matrix, (matrix + (dim1 * dim2)), 0);
If you want to access a value at <row, column>:
int value = matrix[(row * column) + column];
Since the matrix was one allocation, you only need one delete:
delete [] matrix;

c++ Declaring a 2D array as a global variable

I am struggling to figure out how to declare a 2D Array as a global variable so i can use it in all of my methods. So far it is only declared in a single method hence why it cannot be used in other methods.I have figured out how to declare a normal string array by just typing string* array = new string[1] at the start of my code before the methods (i then alter the size of this array later on based of a variable) but i am unsure how to do it with a 2D array:
void WordSearch::ReadSimplePuzzle()
int columns = 9;
int rows = 9;
string **simple2DArray = new string*[columns];
for (int i = 0; i < columns; i++)
simple2DArray[i] = new string[rows];
//code that populates the array too long to post but not relevant.
I then have a method later on where i need to access the simple2DArray but i cannot figure out how to define it at the start of the code any help would be appreciated.
If you columns and rows variables never change, you can do this:
const int columns = 9;
const int rows = 9;
string simple2DArray[columns][rows];
By statically allocating the memory, you now don't have to worry about freeing it.
Since you clarified that the size is not known until run-time, you will not be able to allocate the memory statically. A very simple solution would be:
std::vector<std::vector<std::string>> simple2DArray; // This will have size 0 at start
Then, in your initialization step, just do this:
simple2DArray.resize(rows);
for (auto& row : simple2DArray)
{
row.resize(columns);
}
There are other ways to do this, of course, such as allocating all the memory in one block of size rows*columns and then exposing it as if it were a 2-d matrix but that might be overkill for your purposes.
My suggestion is hide the array behind a functional interface.
std::string const& getElement(size_t m, size_t n);
void setElement(size_t m, size_t n, std::string const& val);
The calling functions have the abstractions of a 2D array but they don't need to know how the it is represented in code.
In the implementation, you have various options:
Use a 1D array. Map the 2D indices to the right index in the 1D array.
Use a std::vector. Still need to map the indices.
Use a 2D array. No mapping of indices needed.
Use a std::vector<std::vector<std::string>>. No mapping of indices needed.
I am struggling to figure out how to declare a 2D Array as a global
variable so i can use it in all of my methods.
As with any global var, you need to declare your pointer in global space:
string **simple2DArray;
and then you can assign to it from inside your method
simple2DArray = new string*[columns];
If you are asking this for making it easier to solve competitive programming problems, then look at the constraints given in the question. For example if the matrix can be an N*N with 1 <= N <= 1000 Then you can globally declare int arr[1000][1000];
Here's some code for a better idea.
//global declarations
int N;
int arr[1000][1000];
int functionA()
{
// some code
}
int functionB()
{
// some code
}
int main()
{
// Get the input of both N and your array arr
// Now you can use them in any where in your code
}

How to init a double**?

I need to init/use a double ** (decleared in my header):
double **pSamples;
allocating (during the time) a matrix of NxM, where N and M are get from two function:
const unsigned int N = myObect.GetN();
const unsigned int M = myObect.GetM();
For what I learnt from heap and dynamic allocation, I need keyword new, or use STL vector, which will manage automatically allocate/free within the heap.
So I tried with this code:
vector<double> samplesContainer(M);
*pSamples[N] = { samplesContainer.data() };
but it still says I need a constant value? How would you allocate/manage (during the time) this matrix?
The old fashioned way of initializing a pointer to a pointer, is correctly enough with the new operator, you would first initialize the the first array which is a pointer to doubles (double*), then you would iterate through that allocating the next pointer to doubles (double*).
double** pSamples = new double*[N];
for (int i = 0; i < N; ++i) {
pSambles[i] = new double[M];
}
The first new allocates an array of double pointers, each pointer is then assigned to the array of pointers allocated by the second new.
That is the old way of doing it, remember to release the memory again at some point using the delete [] operator. However C++ provide a lot better management of sequential memory, such as a vector which you can use as either a vector of vectors, or simply a single vector capable of holding the entire buffer.
If you go the vector of vector way, then you have a declaration like this:
vector<vector<double>> samples;
And you will be able to reference the elements using the .at function as such: samples.at(2).at(0) or using the array operator: samples[2][0].
Alternatively you could create a single vector with enough storage to hold the multidimensional array by simply sizing it to be N * M elements large. However this method is difficult to resize, and honestly you could have done that with new as well: new double[N * M], however this would give you a double* and not a double**.
Use RAII for resource management:
std::vector<std::vector<double>> samplesContainer(M, std::vector<double>(N));
then for compatibility
std::vector<double*> ptrs(M);
for (std::size_t i = 0; i != M; ++i) {
ptrs[i] = samplesContainer[i].data();
}
And so pass ptrs.data() for double**.
samplesContainer.data() returns double*, bur expression *pSamples[N] is of type double, not double*. I think you wanted pSamples[N].
pSamples[N] = samplesContainer.data();

How to get the dimensions of a 2d dynamic array of strings in C++?

I have a dynamically populated array of strings in C++:
string** A;
it is populated like this:
A = new string*[size1];
and then:
for (unsigned int i = 0; i < size1; i++)
{
A[i] = new string[size2];
for (unsigned int j = 0; j < size2; j++)
{
A[i][j] = whatever[j];
}
}
elsewhere, I want to find out the dimensions (size1 and size2).
I tries using this:
sizeof(A[i]) / sizeof(A[i][0])
but it doesn't work.
Any ideas ?
Thanks
When you allocate memory via new T[N], the value N is not stored anywhere . If you need to know it later, you will need to keep track of it in your code.
There are pre-existing classes for allocating memory that also remember the length that was allocated. In your code:
vector<vector<string>> A(size1, vector<string>(size2));
// (code to populate...)
then you can access A.size() to get size1, and A[0].size() to get size2.
If the dimensions are known at compile-time you may use array instead of vector.
It is very simple to find the size of a two dimensional (more exactly of one-dimensional dynamically allocated arrays) array. Just declare it like
std::vector<std::vector<std::string>> A;
and use
std::cout << A.size() << std::endl;
As for your approach then you have to store the sizes in some variables when the array is allocated.
If you are learning C++, I would recommend that you learn Classes. With a class you can encapsulate int variables along with your 2D array that you can use to store the dimensions of your array. For example:
class 2Darray{
string **array;
int rows;
int cols;
}
You can then get the dimensions of your 2Darray object anytime by reading these member variables.
vectors will do this for you behind the scenes but its good for you to learn how to do this.
You can't create an array just using pointer operator. Every array is basically a pointer with allocated memory. That's why compiler wants constant before creating array.
Basically; sizeof(A[i]) won't give you the size of array. Because sizeof() function will return the a pointers size which is points to A[i] location. sizeof(A[i]) / sizeof(A[i][1]) will probably give you 1 because you are basically doing sizeof(int)/sizeof(int*)
So you need to store the boundary yourself or use vectors. I would prefer vectors.
Can't get array dimensions through pointer(s)

Creating a dynamic 2D array

I need to have a 2D array of double.
Its width is around 900. Its height as well (the same width value).
Dealing with two loops (one for the width and one for the height), I really need to get access to all the pixels of the 900X900 image that I will process.
The size of the array is too big (error when specifying the number of raw and column).
I thought about establishing that with a dynamic array to optimize the time of calculation and to free the memory everytime I deal with one pixel on the two loops.
But I really cannot find the syntax I would like to have to declare a 2D dynamic array (malloc, setting array element values and freeing the memory).
Wrap it in a class:
class Matrix2D {
typedef std::vector<double> Column;
std::vector<Column> columns;
public:
Matrix2D(unsigned int width, unsigned int height) :
columns(width, Column(height)) {
}
double& at(unsigned int i, unsigned int j) {
return columns[i][j];
}
};
Matrix2D matrix(900, 900);
matrix.at(45, 65) = 1234.5678;
I need to have a 2D array of double
Since you are using C++ you should use STL classes that will take care of ugly memory management for you. So you are actually looking for std::vector< std::vector<double> >, or for the sake of the readability of your code:
#include <vector>
typedef std::vector<double> DVector; // row represented by vector of doubles
typedef std::vector<DVector> MyVector; // 2D array as a vector of these rows
And then avoid using dynamic allocation wherever it's possible to do so. Take advantage of RAII idiom:
{
MyVectorarr; // vector object with automatic storage duration
} // <-- vector is automatically destructed when execution goes out of scope
Questions that might help you:
Multi-dimensional vector
Initialization of a vector of vectors?
vector of vector
I associate malloc with pure C, not C++ (as the prior answer points yout, you should use std::vector). However, if you really want to:
// allocate the memory in a block
double* block = (double *) malloc(sizeof(double) * xSize * ySize);
// allocate memory for the accessor array
double* accessor = (double*) malloc(sizeof(double*) * xSize);
// assign memory addresses
double* curPtr = block;
for (int i = 0; i < xSize; ++i) {
accessor[i] = curPtr;
curPtr += ySize;
}
// you can now access the array via accessor[x][y]
// now need to free malloced memory:
free(accessor);
free(block);
If you do it this way, I highly suggest tying it to the RAII pattern, otherwise you'll eventually get a memory leak. Using the STL's containers is a better approach.