c++ How to deallocate and delete a 2D array of pointers to objects
You have a tonne of deleting to do in this:
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
delete matrix_0[i][j]; // delete stored pointer
}
delete[] matrix_0[i]; // delete sub array
}
delete [] matrix_0; //delete outer array
matrix_0 = NULL;
There is no need to NULL
anything except matrix_0
because they are gone after delete.
This is horrible and unnecessary. Use a std::vector
and seriously reconsider the pointer to the contained object.
std::vector<std::vector<Object*>> matrix_0(rows, std::vector<Object*>(cols));
Gets what you want and reduces the delete work to
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
delete matrix_0[i][j]; // delete stored pointer
}
}
But SergeyA's suggestion of storing unique_ptr
, std::vector<std::vector<std::unique_ptr<Object>>> matrix_0;
reduces the deletions required to 0.
Since speed is one of OP's goals, there is one more improvement:
std::vector<std::unique_ptr<Object>> matrix_0(rows * cols);
Access is
matrix_0[row * cols + col];
This trades a bit of visible math for the invisible math and pointer dereferences currently going on behind the scenes. The important part is the vector is now stored as a nice contiguous block of memory increasing spacial locality and reducing the number of cache misses. It can't help with the misses that will result from the pointers to Objects
being scattered throughout memory, but you can't always win.
A note on vector
vs array. Once a vector
has been built, and in this case it's all done in one shot here:
std::vector<std::unique_ptr<Object>> matrix_0(rows * cols);
all a vector
is is a pointer to an and a couple other pointers to mark end and the the location of the last location used. Access to the data array is no different from access to a dynamic array made with new
. Using the index operator []
compiles down to data_pointer + index
exactly the same as using []
on an array. There is no synchronizing or the like as in Java's Vector. It is just plain raw math.
Compared to a dynamic array all a preallocated vector
costs you is two pointers worth of memory and in return you get as close to no memory management woes as you are likely to ever see.
Deleting a dynamically allocated 2D array
In reality, an array of pointers pointed to by a pointer is still an array of integral data types or numbers to hold the memory addresses. You should use delete[]
for both.
Also, yes, a new[]
implies a delete[]
.
When you create an array of arrays, you're actually creating an array of numbers that happen to hold the memory address for another array of numbers. Regardless, they're both arrays of numbers, so delete both with delete[]
.
http://coliru.stacked-crooked.com/a/8a625b672b66f6ce
#include <iostream>
int main() {
//Hey, pointers have a finite size, no matter the indirection level!
std::cout << "sizeof(int*): " << sizeof(int*) << std::endl;
std::cout << "sizeof(int**): " << sizeof(int**) << std::endl;
std::cout << "sizeof(int***): " << sizeof(int***) << std::endl;
//Create an array of pointers that points to more arrays
int** matrix = new int*[5];
for (int i = 0; i < 5; ++i) {
matrix[i] = new int[5];
for (int j = 0; j < 5; ++j) {
matrix[i][j] = i*5 + j;
}
}
//Print out the matrix to verify we have created the matrix
for (int j = 0; j < 5; ++j) {
for (int i = 0; i < 5; ++i) {
std::cout << matrix[j][i] << std::endl;
}
}
//Free each sub-array
for(int i = 0; i < 5; ++i) {
delete[] matrix[i];
}
//Free the array of pointers
delete[] matrix;
return 0;
}
Delete pointer to 2d array
// Code is not tested
for(int i = 0 ; i < x ; ++i)
{
for(int j = 0 ; j < y ; ++j)
{
delete rob[i][j];
}
delete[] rob[i];
}
delete[] rob;
By the way, why do you set rob[i][j] = NULL;
?
I think it should be : rob[i][j] = new double;
Function to delete dynamically allocated 2D array
Is this the correct way for a function to clear said memory?:
Yes.
Key note: Do I pass just a double pointer or a double pointer reference to the function for deleting?
Both work. I recommend not using a reference since that will be less confusing to the reader.
However, I recommend avoiding owning bare pointers in the first place. In this case, std::vector<std::vector<int>>
could be appropriate.
Or, more efficient (probably; depends on how you intend to use it) alternative would be to use a single dimensional vector and translate the indices.
Access the elements of a multidimensional array through a pointer in another class
You should do this:
pathFind::pathFind(int (*map)[20] ){
costMap = map;
}
That is, match the types!
Also note that T (*)[N]
and T**
are not compatible types. One cannot convert to other. In your code, you're trying to do that, which is what the error message tells you.
Besides, there are other issues with your code, such as you should avoid using new
and raw-pointers. Use std::vector
or other containers from the Standard library, and when you need pointer, prefer using std::unique_ptr
or std::shared_ptr
whichever suits your need.
Related Topics
Is Using an Union in Place of a Cast Well Defined
Error: 'I' Does Not Name a Type with Auto
How to Convert a Time into Epoch Time
Static Array Class Variable "Multiple Definition" C++
C++11 Std::Async Doesn't Work in Mingw
Finding the Position of the Maximum Element
Are the Character Digits ['0'..'9'] Required to Have Contiguous Numeric Values
Simple String Parsing with C++
Correct Usage of the Eigen::Ref<> Class
Is There a More Efficient Implementation for a Bidirectional Map
Is There a Proper 'Ownership-In-A-Package' for 'Handles' Available
Reference Invalidation After Applying Reverse_Iterator on a Custom Made Iterator
If a 32-Bit Integer Overflows, How to Use a 40-Bit Structure Instead of a 64-Bit Long One
Strange Behaviour of MACros C/C++