I want to store pointers (Bar *) in a multidimensional-array of 2 dimensions. And I want to access to this array from a pointer.
So I want to initialize a **foo[][] (or ****fo).
Bar ****_bars; // declaration
int n, m; // dimensions size
_bars = new Bar ***;
*_bars = new Bar **[n];
for (int i = 0; i < n; i++) {
*_bars[i] = new Bar *[m];
for (int j = 0; j < m; j++) {
*_bars[i][j] = new Bar();
}
}
My app crash at line *_bars[i][j] = new Bar(); when i=0 and j=1.
Your problem is likely the precedence of the [] and * operators (see this answer). For example, in your case the expression *_bars[i] is evaluated like:
*(_bars[i]) = ....
Since there is only one element in _bars[] you run into "issues" with _bars[1]. Same thing with *_bars[i][j].
But really, please use std::array<> or std::vector<> for something like this.
Related
I have an array called int **grid that is set up in Amazon::initGrid() and is made to be a [16][16] grid with new. I set every array value to 0 and then set [2][2] to 32. Now when I leave initGrid() and come back in getGrid() it has lost its value and is now 0x0000.
I don't know what to try, the solution seems to be really simple, but I'm just not getting it. Somehow the data isn't being kept in g_amazon but I could post the code.
// Returns a pointer to grid
int** Amazon::getGridVal()
{
char buf[100];
sprintf_s(buf, "Hello %d\n", grid[2][2]);
return grid;
}
int Amazon::initGrid()
{
int** grid = 0;
grid = new int* [16];
for (int i = 0; i < 16; i++)
{
grid[i] = new int[16];
for (int j = 0; j < 16; j++)
{
grid[i][j] = 0;
}
}
grid[2][2] = 32;
return 0;
}
int **grid;
g_amazon = Amazon::getInstance();
g_amazon->initGrid();
grid = g_amazon->getGridVal();
for (int i = 0; i < 16; i++)
{
for (int j = 0; j < 16; j++)
{
int index;
index = (width * 4 * i) + (4 * j);
int gridval;
gridval = grid[i][j];
lpBits[index] = gridval;
lpBits[index + 1] = gridval;
lpBits[index + 2] = gridval;
}
}
It crashes when I run it at the line where sprintf_s prints out [2][2] and it also crashes when I get to gridval = grid[i][j] because it's at memory location 0x000000.
The variable
int** grid
in the initGrid() function is a local variable. Edit** When the function returns the variable is popped off the stack. However, since it was declared with the new operator the memory still exists on the heap; it is simply just not pointed to by your global grid variable.
#Dean said in comment:
I have grid as an int** grid; in class Amazon {}; so shouldn't it stay in memory or do I need a static var.
That is the problem:
local int **grid; on Amazon::initGrid::
is masking
member int **grid; on Amazon::
as the first context has higher priority in name lookup.
So initGrid() allocates memory referenced only by a local pointer. That pointer no longer exists when you return from this function, Amazon::grid was never touched on initialization and you're also left with some bad memory issues.
So, as commented by #Remy-Lebeau, I also suggest
Consider using std::vector> or std::array, 16> instead. There is no good reason to use new[] manually in this situation.
In main I can:
Node* myNodeArray2[myHeight][myWidth];//Does not call constructor
for(int i=0; i<myHeight; i++){
for(int j=0; j<myWidth; j++){
theNodeArray[i][j] = new Node("ThisIsTest", 5, 5);
}
}
So for the above code myHeight and myWidth can be user input at run time. It does not call the default constructor and I can use the new operator and go through the array creating the objects.
I want to be able to pass Node* myNodeArray2 to a function and let it create the array size and populate it. When it is created I want the elements to be pointers. I don't want to call the default constructor. I want to be able to at my choosing call the new operator with the non-default constructor.
When I try:
void Test(Node*& theNodeArray, int myHeight, int myWidth){
theNodeArray = new Node*[myHeight][myWidth];
}
int main(){
Node* myNodeArray;
Test(myNodeArray, myHeight, myWidth);
}
I get that
"myWidth is not a constant expression."
I have tried a couple of different methods but cannot get what I want. I need the creation to happen in a separate function. I need to be able to define the size at runtime. Any help?
Edit:
I don't want to use std::vector.
Edit 2:
I don't want to do this
int** ary = new int*[sizeX];
for(int i = 0; i < sizeX; ++i)
ary[i] = new int[sizeY];
As this forces the rows to be of objects of contiguous memory space. I want to allocate a 2d array of pointers. I do not want to necessarily create the objects that will be pointed to.
You may use the following:
Node*** MakeArrayNodePtr(int myHeight, int myWidth){
Node*** res = new Node**[myHeight];
for (int i = 0; i != myHeight; ++i) {
res[i] = new Node*[myWidth]();
}
return res;
}
And don't forget
void DeleteArrayNodePtr(Node*** nodes, int myHeight, int myWidth)
{
for (int i = 0; i != myHeight; ++i) {
// And probably:
/*
for (int j = 0; j != myWidth; ++j) {
delete nodes[i][j];
}
*/
delete [] nodes[i];
}
delete [] nodes;
}
int *array[10];
for(int i = 0; i < 10; i++)
array[i] = new int[10];
//...
void passFunc(int *a[10]) //array containing pointers
{
//...
}
passFunc(array);
Im trying to figure out how to declare and delete this version of a 2D array. I started using int ** array, but in order to make one section of code easier, I need to switch to *[]. Can anyone help me out?
I have tried compiling my actual code (the above code is just an example), which looks like this:
int* filedata[LENGTH] = new int*[LENGTH]; //ERROR: array must be initialized with brace- enclosed identifiers.
EDIT:
Thanks!
Something like that
int** array = new int*[sizeX];
for(int i = 0; i < sizeX; ++i)
array[i] = new int[sizeY];
To delete
for(int i = 0; i < sizeX; ++i)
delete [] array[i];
delete [] array;
If I have understood correctly what you want then the allocation and deallocation will look as
int ** filedata = new int * [LENGTH];
for ( int i = 0; i < LENGTH; i++ ) filedata[i] = new int [LENGTH];
//...
for ( int i = 0; i < LENGTH; i++ ) delete [] filedata[i];
delete [] filedata;
Alternate version to the ones given:
int** array = new int*[sizeX];
int *pool = new int[sizeX * sizeY];
for(int i = 0; i < sizeX; ++i, pool += sizeY)
array[i] = pool;
To delete:
delete [] array[0];
delete [] array;
The advantage of using this is:
Only two calls to new[] and delete[] are required, regardless of the number of columns. In the previous answer, the number of calls to new and delete depend on the number of columns. This reduces fragmentation, and also will probably give you a speed increase if the number of columns is very large.
The data is contiguous. You can access any element in the 2d array from any other element using a simple offset.
The disadvantage is that the number of columns for each row needs to be the same, otherwise it becomes very difficult to maintain.
I get very frustrating error in following piece of code. Thats my array.
int **tab2 = new int*[3];
I allocate this like it.
for(i = 0; i < 10; i++) {
tab2[i] = new int[3];
tab2[i][0] = 40;
tab2[i][1] = 10;
tab2[i][2] = 100;
}
Then after using it i want to destroy it.
for(i = 0; i < 10; i++) {
delete [] tab2[i];
}
delete [] tab2;
And this causes core dump every single time. I tried many different ways to destroy it and every time get this error. What im making wrong here ?
This
int **tab2 = new int*[3];
does not do what you think it does.
You want an array that will contain TEN (10) pointers, each to an array of THREE ints.
new int*[3] is an array that contain THREE pointers.
What you want is this (live at coliru):
#include <iostream>
int main() {
int **tab2 = new int*[10];
for(int i = 0; i < 10; i++) {
tab2[i] = new int[3];
tab2[i][0] = 40;
tab2[i][1] = 10;
tab2[i][2] = 100;
}
for(int i = 0; i < 10; i++) {
delete [] tab2[i];
}
delete [] tab2;
}
With
int **tab2 = new int*[3];
you allocate an array of pointers of size 3. But than with
for(i = 0; i < 10; i++) {
tab2[i] = new int[3];
//...
}
you access it with up to index 9. That will surely go wrong.
The deletion process looks fine to me. To fix it, you should allocate an array of pointers with size 10instead of 3, e.g.
int **tab2 = new int*[10];
Looks like what you're trying to do is to create an N by M array, where N is known at runtime and M is fixed (in this case, 3).
Why not just do this?
{
std::array<int, 3> defaults = {{ 40, 10, 100 }};
std::vector<std::array<int, 3>> thing(10, defaults);
}
The vector, thing is automatically deallocated when it goes out of scope, and its size can be set at runtime. You still access the structure in the same way:
thing[1][2] = 3
Manual memory management can be easily avoided by using standard containers and smart pointers. Doing so will keep you code cleaner, and have fewer opportunities for dangling pointers and memory leaks.
Okay, so here's the context. I've been up for almost a day straight now working on the legendary 8-puzzle problem. I have my heuristics down and my A_star algorithm down. We are required by the project spec to solve it using three different heuristic values. I can solve it for any one of the three individually, but when I go to solve them in succession, I get a ridiculous loop, and it never finds the correct successor state.
I believe my problem is with my pointers. I have a class, State, as defined below that has an int** array and a pointer to a State (its parent).
EDIT: I have to use int** as defined by the project specification, otherwise I would gladly use a pointer.
State (int **bd, State* prnt);
State (const State& other);
~State ();
I am then declaring them as such:
State::State(int **bd, State* prnt) {
// allocate the board
board = new int*[3];
for (int i = 0; i < 3; i++) {
board[i] = new int[3];
}
// fill in the board
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
board[i][j] = bd[i][j];
//board[i][j] =
}
}
// set the parent
parent = prnt;
}
State::State(const State& other) {
// allocate the board
board = new int*[3];
for (int i = 0; i < 3; i++) {
board[i] = new int[3];
State::~State() {
//std::cout << "Deconstructing " << this << endl;
for (int i = 0; i < 3; i++)
delete board[i];
delete [] board;
delete parent;
parent = other.parent;
}
State::~State() {
//std::cout << "Deconstructing " << this << endl;
for (int i = 0; i < 3; i++)
delete board[i];
delete [] board;
delete parent;
}
State& State::operator=(const State &rhs) {
if (&rhs == this) {
return *this;
}
for (int i = 0; i < 3; i++) {
delete board[i];
}
delete [] board;
// allocate the board
board = new int*[3];
for (int i = 0; i < 3; i++) {
board[i] = new int[3];
}
// fill in the board
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
//board[i][j] = rhs.board[i][j];
board[i][j] = rhs.getIntAtCoor(j, i);
}
}
//delete parent;
// set the parent
parent = rhs.parent;
// set g
g = rhs.g;
f = rhs.f;
hType = rhs.hType;
return *this;
}
I don't give the exact declarations -- some of it is simple like int = int. I just can't quite figure it out. I feel like either my delete parent is wrong or my parent = other.parent is wrong (or both).
Thank you for your time and help,
Tyler
Upgrading your code-style may force the errors to evaporate. In other words new and delete are error prone and should be avoided when better alternative exists.
For management of the cells consider:
std::shared_ptr: can be used to void the delete calls
std::vector can be used to avoid the new and delete calls
Note you should use it like std::vector<int> board( 3 * 3 ) and board.at( x + y * 3 ).
And best of all just use a static array int board[3][3]. No allocation at all.
Also child states do not own their parent states. It's the other way around. So child states shouldn't delete their parents. You can still safely keep a parent pointer, but make sure you cleanup the children before you allow a parent to go out of scope (deleted or otherwise). All of this cleaning and deleting doesn't neccessarily involve new at all. Your State class looks small enough that is doesn't matter if they are copied by value. In which case just have the parent use a std::vector<State> m_children and the compiler will take care of the rest.
You don't show the full definition of the copy constructor but I assume that the parent = other.parent line is in there. In that case, wouldn't the parent be responsible for its own lifetime and the delete parent in the destructor shouldn't exist at all.
Also note that you need to at least disable (private declaration) or implement the copy assignment operator.
Better still, use a vector of vector for your 2d array and let the language work for you.
Perhaps not a direct answer, but you are going against best practices for C++.
It's easier and definitely more maintainable to use vectors for this problem.
size_t row_sz = 3;
size_t col_sz = 3;
std::vector<int> board(row_sz * col_sz, 0);
int i = 0;
for (size_t r = 0; r < 0; r++)
for (size_t c = 0; c < 0; c++)
board[ r * row_sz + c ] = i++;
Multidimensional arrays are much easier handled with the above strategy as well. It just breaks less. If you really want the row/col access, write a wrapper around it.
struct Matrix {
int &operator()(size_t r, size_t c);
const int &operator()(size_t r, size_t c) const;
private:
std::vector<int> data;
};