Creating a temporary array with pointers C++ - c++

I was wondering if this is the proper way create a temporary array using pointers in a class. Part of my problem says this:
getMedian – returns the median value of the array. See Chapter 10 Programming Challenge 6 (p. 693) for a discussion of the term median. Taking the median will require a sorted array. You will need to create a temporary array to sort the values (to preserve the ordering of numbers). Do not sort the private member numbers array. Dynamically allocate/deallocate a temporary array in your getMedian function to determine the median.
My code:
double Statistics::getMedian() const
{
int tempArray[length];
for (int k = 0; k < length; k++){
tempArray[k] = numbers[k];
}
bubbleSort(tempArray);
return 0;
}
Before obviously doing the median part and a proper return statement, is this.
How you properly copy over a temporary array to alter for this problem? I don't think it is because I'm not properly allocating or deallocating anything, but I don't understand how to create a temporary array without altering the original.

Your assignment says you are to allocate/deallocate the array dynamically. That means (in C++) using new and delete. Since you want an array, you should use array space allocator operators new[] and delete[].
double Statistics::getMedian() const
{
int *tempArray = new int[length];
for (int k = 0; k < length; k++){
tempArray[k] = numbers[k];
}
// work with tempArray
delete[] tempArray;
return 0; // or the median
}
EDIT:
As suggested in the comment below, modern (C++11 and newer) way is to use smart pointers. That would mean your code could look like this.
#include <memory>
double Statistics::getMedian() const
{
std::unique_ptr<int[]> tempArray (new int[length]);
for (int k = 0; k < length; k++){
tempArray[k] = numbers[k];
}
// work with tempArray like you would with an old pointer
return 0; // or the median
// no delete[], the array will deallocate automatically
}
Check unique_ptr template class for more details. Note that this solution might not be what your professor wants, especially when the assignment talks about deallocation.

Related

Why do I have to free 2D array twice to avoid memory leak?

I am running into a memory leak problem when allocating a 2D array.
But I could not understand why the memory leaks.
My reasoning is that at Note A, I have already freed allocated memory, since data_[0] == data_, why do I have to do the free at Note B?
class Matrix {
public:
Matrix(int r, int c) {
this->rows = r;
this->cols = c;
data_ = new int*[r];
for (int i = 0; i < r; i++) {
data_[i] = new int[c];
}
}
~Matrix() {
for (int i = 0; i < this->rows; i++) {
delete [] data_[i]; // Note A;
}
delete[] data_; // Note B; <-- not doing this line will leak memory, but why?
}
private:
int rows;
int cols;
int **data_;
};
What you post there isn't really a 2D array, it's a 1D array-of-pointers (data_), and then you allocate a separate array-of-ints for each element of the first array (so data_[0] is an array of c ints, data_[1] is an array of c ints, and so on).
Given that, it's natural that you'll have to do one delete[] in your destructor for each new that you performed earlier in your constructor.
A graphical diagram of your memory allocations and how they point to each other might look like this (if c==6 and you have set all of your arrays' integers to 0):
A real 2D array allocation would look like this: int * array2D = new int[6][8];, but of course C++ only supports 2D arrays if the array-dimenions are compile-time constants, so that probably wouldn't solve the problem your Matrix class is meant to solve.
When you have created 2D array (for example 3x3), you have created 1 array with 3 elements, where each element is pointer to separate array. So to clear memory for this matrix you need to clear 4 arrays (3 rows and 1 array containing pointers).
You can check how many times in your code you are calling new operator
it will be r+1 times
data_ = new int*[r];// 1 time
for (int i = 0; i < r; i++ {
data_[i] = new T[c]; // r times
}
Part I:
The line data_ = new int*[r]; allocates and default initializes a dynamic array of int* through new, so you would need to provide a corresponding delete [] data_; for this line.
Part II:
The line data_[i] = new int[c]; dynamically allocates and default initializes an int array and then the pointer to that first element is returned and stored as the data_[i] element. So here again you would need a corresponding delete [] data_[i]; to get rid of the memory leak.
So these were the reasons why you need two separate delete []. The process is as shown in the screenshot. Also note that the important thing is the default initialization. So the int array elements will not all have a value 0 as wrongly shown in the answer by #Jeremy Friesner.

Free dynamic array of static arrays?

I have code similar to this
EDIT this code is supposed to be on interface so only POD is allowed. No vectors, no containers.
int (*neco)[2];
int ahoj = 2;
neco = new int[ahoj+2][2];
int iter = 1;
for (size_t i = 0; i < 4; i++)
{
for (size_t j = 0; j < 2; j++)
{
neco[i][j] =iter;
iter++;
}
}
for (size_t i = 0; i < ahoj + 2; i++)
{
delete[] neco[i];
}
This does not work. The delete deletes memory not allocated.
Not even
delete[] neco;
Or any other delete. Everyone of them deletes memory BEFORE the allocated block.
Googling and consulting with peers in the office had no results. :)
How do I allocate dynamic array of "points" (two coordinates) and then free them?
I am able to solve the problem via using different structure.
But apperently I am able to allocate the memory. Write in the allocated memory…
How do I correctly free this memory? (Just accademic question.)
Plain pointers to dynamically allocated memory get you into troubles.
Use a std::unique_ptr:
#include <memory>
// ...
std::unique_ptr<int[][2]> neco(new int[ahoj+2][2]);
And remove that loop with delete[].
Alternatively, use std::vector<int[2]> neco(ahoj+2) - it does memory management for you and can be resized.
The general rule is that every new expression must be matched by a single corresponding delete expression.
Your new expression is the right hand side of the statement
neco = new int[ahoj+2][2];
so the corresponding delete expression is given in the statement
delete [] neco;
If that doesn't work (which is what you claim) it means the problem is in some other code exhibiting undefined behaviour.
Your loop
for (size_t i = 0; i < ahoj + 2; i++)
{
delete[] neco[i];
}
is incorrect because none of the neco[i] are the result of a new expression. So delete [] neco[i] has undefined behaviourin every loop iteration.
Given that your code sample(s) and description are incomplete, I doubt anyone else can give more useful advice.
Also, you are mistaken in your belief that you can't use a standard container. You can.
#include <vector>
int main()
{
std::vector<int[2]> avec(ahoj + 2);
int (*neco)[2] = &avec[0];
for (size_t i = 0; i < ahoj + 2; ++i)
{
for (size_t j = 0; j < 2; ++j)
{
neco[i][j] = iter;
++iter;
}
}
}
The only difference is that avec does the dynamic memory allocation and deallocation for you. neco is still a pointer to an array as required (according to your description) by your API. The two constraints on this approach are;
don't resize theavec after initialising neco (or reinitialise neco whenever avec is resized)
don't use neco after avec ceases to exist (since the behaviour will then be undefined).
Also, none of the arrays are actually static. So your question is mistitled.
If I can recall properly, an array of arrays (being dynamic or static), is basicly a matrix.
So, the academic answer:
The same way you allocate memory (first allocate the memory of the array of arrays, then with a foryou allocate the memory of the arrays inside the array), to free it, you need to delete in a forthe memory of the arrays, and then, in a simple delete, free the memory of the dynamic array.
So:
arrayOfArrays[[array1][array2][array3][array4]]
means: allocate memory of arrayOfArrays, then in a loop, allocate memory of array(number)
Same goes the other way around.
Free memory of arrayOfArraysin a single sentence.

C++ Pointer of Array of Ints Initialization

I want to have an array accessible by all functions of a class.
I put the array as private variable in the header file.
private:
int* arrayName;
In the .cpp file where I implement the class, the constructor takes in an int value (size) and creates the array. The goal is to fill it up
ClassName::ClassName(int numElements){
arrayName = new int[numElements]; //make arrays the size of numElements
for(int i = 0; i<numElements; i++)
arrayName[i] = 0;
}
I feel like this is quite inefficient. I know you can do int array[5] = {0}; but how do you do it when you don't initially know the size.
If you want to zero-initialize a newed array, just do value-initialize it. This has the effect of zero-initializing its elements:
arrayName = new int[numElements]();
// ^^
But you really want to be using an std::vector<int>.
private:
std::vector<int> vname;
and
ClassName::ClassName(int numElements) : vname(numElements) {}
This way you don't have to worry about deleting an array and implementing copy constructors and assignment operators.
You can use the memset function:
memset(arrayName,0,sizeof(int)*numElements);
This void * memset ( void * ptr, int value, size_t num ); function sets the first num bytes of the block of memory pointed by ptr to the specified value (interpreted as an unsigned char).
To use it you must include the string.h header file.
For more information: http://www.cplusplus.com/reference/cstring/memset/
What you want to do is progressively expand the array on demand.
arrayName = new int[numElements];
for(int i = 0; i<numElements; i++)
arrayName[i] = 0;
The above code (what you gave) will give you an array of size numElements, and THEN the for loop will fill it. This is allocated now, and can't, as I understand it, be simply or easily resized (memset will overwrite previously held values in the array).
You could copy the whole array over every time you want to resize it:
int * oldarr = new int[OldSize];
//fill your old array
int * newarr = new int[NewSize];
for(int i = 0; i<OldSize; i++)
newarr[i] = oldarr[i];
Other than that, you could make the array much larger, or you could use various STLs, such as std::vector. Vector can be increased with a simple push_back function, and allows [] operator access (like arr[5] and whatnot).
Hope this helps!

proper memory allocation for a 2D array in a class in C++

I am writing a C++ class that uses some fixed arrays, as well as some dynamically allocated arrays.
I was wondering if anybody can guide me for the proper way to allocate memory for the dynamic arrays , probably in the constructor/deconstructor, and also if I need to explicitly call them to make sure I don't get a seg fault.
Here is a simplified version of the related part of my code:
class Network {
public:
int n_nodes;
int user_index[MAX_USERS]; //a fixed array
int adjacency_matrix[][MAX_ITEMS];
//Network(int n_node, int** adjacency); //I would rather to set the element s in a function other than the constructor
Initializer(int n_node, int** adjacency);
~Netowrk();
}
So here are my specific question for this class:
1 - Can I have the 2D array adjacency_matrix[][] with undecided number of rows and columns until it's set by the user in the initializer function?
2 - where should I delete the 2D array? should I write it in the deconstructor? Should I call the deconstructor explicitly? Is there anything else I need to destroy in the deconstructor?
1 - Can I have the 2D array adjacency_matrix[][] with undecided number of rows and columns until it's set by the user in the initializer function?
Yes. The best way to do this, however, is not to use arrays at all. Instead, use std::vector, which manages the memory for you. There are two ways that you can do this. If you actually want to be able to use the [row][column] syntax to access elements, you'll need to use two dimensions of std::vectors:
std::vector<std::vector<int> > adjacency_matrix;
Once you know the dimensions, you can populate it:
adjacency_matrix.assign(rows, std::vector<int>(columns));
It is often easier to use a single-dimensional array (or a std::vector<int>) containing all of the elements and use row * row_count + column to access the element at index (row, column). This way, there are fewer dynamic allocations. You can wrap up the logic of accessing elements into a couple of helper functions.
2 - where should I delete the 2D array? should I write it in the deconstructor?
You don't have to delete anything if you use a std::vector. It cleans itself up.
Should I call the [destructor] explicitly?
No.
Is there anything else I need to destroy in the [destructor]?
Ideally, no. If you use the Standard Library containers, like std::vector and smart pointers, you shouldn't have to clean anything up. You should avoid trying to manage resources on your own in C++: there are library facilities to do this tedious task for you and you should take advantage of them.
1 - Can I have the 2D array adjacency_matrix[][] with undecided number of rows and columns until it's set by the user in the initializer function?
Yes you can. For example:
int* adjacency_matrix_;
int* getAdjacency(int i, int j)
{
if (!adjacency_matrix_)
return 0;
else
return adjacency_matrix_ + i*n_nodes + j;
}
Network()
: n_nodes(0),
adjacency_matrix_(0)
{}
void Initializer(int n_node, int** adjacency)
{
adjacency_matrix_ = new int[n_nodes * n_nodes];
// Copy over data.
}
As to whether you should, that depends on whether you have a reason for not using std::vector<>.
2 - where should I delete the 2D array? should I write it in the deconstructor?
Should I call the deconstructor explicitly?
Is there anything else I need to destroy in the deconstructor?
Yes, definitely free in the destructor using array operator delete:
~Network()
{
delete [] adjacency_matrix_;
}
No, your destructor will be called whenever the Network object itself goes out of scope. It is (very) rarely necessary to make an explicit destructor call.
No, all a destructor needs to explicitly release is whatever your explicitly acquire.
You may like the example matrix class I wrote in an answer to another question
The question itself was about good C++ design practices, but the chosen example was a multi-dimensional array.
There are several ways to do this.
The easiest way is to use vectors, and if you don't like to manage your own memory, this is perfect for you. However, because I like to manage my own memory, and I have found this method to be slow and cumbersome at times, I have learned of other ways.
The fastest way is to allocated a one dimensional array and treat it as you would a two dimensional array. Here is an example:
int *array = new int[width*height];
int get_array(int column, int row)
{
return array[row*width + column];
}
delete [] array;
This can be generalized to the nth-dimension:
int *array = new int[w1*w2*...*wn];
int get_array(int i1, int i2, ..., int in)
{
return array[in*(w1*w2*...*w(n-1)) + i(n-1)*(w1*w2*...*w(n-2)) + ... + i2*w1 + i1];
}
delete [] array;
If you want to be able to have different widths for each row, then you can make an array of pointers. This solution is slow to initialize and clean up, but flexible, tunable, and has relatively fast execution time. It can also be extremely dangerous if you make a mistake though.
int **array = new int*[height];
for (int i = 0; i < height; i++)
array[i] = new int[width(i)];
at which point, to access it, all you have to do is the customary
array[i][j]
however, to free this array you have to do it row by row
for (int i = 0; i < height; i++)
delete [] array[i];
delete [] array;
This can also generalize to the nth dimension.
int **....*array = new int**...*[w1];
for (int i1 = 0; i1 < w1; i1++)
{
array[i1] = new int**..*[w2];
for (int i2 = 0; i2 < w2; i2++)
{
array[i1][i2] = new int**.*[w3];
...
for (int in = 0; in < wn; in++)
array[i1][i2]...[in] = new int[wn];
}
}
for (int i1 = 0; i1 < w1; i1++)
{
for (int i2 = 0; i2 < w2; i2++)
{
...
for (int in = 0; in < wn; in++)
delete [] array[i1][i2]...[in];
...
delete [] array[i1][i2];
}
delete [] array[i1];
}
delete [] array;
This kind of setup tends to wreak havoc on memory. Just a two dimensional array of these would result in width+1 separate arrays to be malloc-ed. It would be faster to just malloc one big array and figure out the indices yourself.

How do you delete (or fill with specific values) a static n-dimension array?

const int ROWS = 3;
const int COLUMNS = 4;
void fillArray(double a[ROWS][COLUMNS], double value);
void deleteArray(double a[ROWS][COLUMNS]);
int main () {
double a[ROWS][COLUMNS];
fillArray(a, 0);
deleteArray(a);
}
In C++, how do you delete (or fill with specific values) a static n-dimension array?
In C++ we generally do not use arrays. We use std::vector.
You can use memset or std::fill to fill the array with specific values.
BTW you can use delete on dynamically allocated arrays not on static ones.
memset( a, 0 ,ROWS * COLUMNS * sizeof( double ));
or
std::fill(&a[0][0], &a[0][0]+sizeof(a)/sizeof(double), 0);
You can delete only an object created by new (and that object will be allocated in the heap). What do you mean by "deleting a static POD variable"? It has no sense:
1) It doesn't have any destructor to perform additional tasks before freeing the memory,
2) The stack memory will be "freed" as you exit the current block.
And to set it: either loop, either simple memset(a, 0, sizeof(a)); .
Also, the array in your example is not static.
std::vector is what is generally used for C++ arrays (especially when you're new at it). One of vector's constructors will fill it for you to:
std::vector<type> myVector(initialSize, defaultValue);
If you want multidimensional, you could do a vector of vectors, or boost::multi_array:
boost::multi_array<type, numberOfDimensions> myArray(boost::extents[firstSize][secondSize][thirdSize]);
In that case, you'll need to use the multiple-for-loops approach, because it doesn't seem to have a constructor that does that.
EDIT: Actually you can use std::vector to make a multidimensional array with default values:
std::vector<std::vector<double> > a(3, std::vector<double>(4, 0));
Where 3 is the number of rows, 4 is the number of columns and 0 is the default value.
What it's doing is create a vector of vectors with 3 rows, where the default value for each row is a vector with 4 zeroes.
Filling arrays in C++ is the same as filling them using C, namely nested for loops
int i, j;
for (i = 0; i < ROWS; i++)
for (j = 0; j < COLS; j++)
a[i][j] = 0
Arrays aren't "deleted" but they can use free if they've been allocated on the heap (if they've been allocated on the stack within a function, this is unnecessary).
int i;
for (i = 0; i < ROWS; i++)
free(a[i]);
free(a);
Firstly, the code you posted seems confused. What is it that you think "deleteArray" is supposed to do? 'a' is an auto variable and therefore cannot be deleted or freed.
Secondly, wrap your array in a class. There is a nice one in the FAQ that you can start with, but it can be improved. The first improvement is to use a vector rather than newing a block of memory. Then std::fill can be used to fill the array.
Use std::fill
#include <algorithm>
And then your implementation is simply:
std::fill(&a[0][0], &a[0][0]+sizeof(a)/sizeof(a[0][0], value);
You don't delete the array since it is stack allocated.