Sign in to follow this  

dynamically allocating a 2D array in a class

This topic is 4729 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm writing a class to easily load bitmaps. Because of this I want to allocate an array the size of which depends on the size of the bitmap I want to load (like this: array[sizeofimage][3] - assuming I'm using an RGB bitmap). anyway, here's a proof of concept (console app) to explain things better. I allocate a 2D array(array[size][3]) and try to fill the array[][1] part with 1's, which I then try to read.
#include <iostream>
using namespace std;

class test
{
public:
	int *p;

	void allocate(int amount)
	{
		int (*p)[3] = new int[amount][3];
	}

	test(int amount)
	{
		allocate(amount);
	}
};

int main()
{
	int number;
	cin >> number;

	test test1(number);
	
	for(int i = 0; i < number; i++)
		test1.p[i][1] = 1;

	for(int j = -1; j < number+1; j++)
		cout << test1.p[j][1] << endl;

	return 0;
}
unfortunately this returns 3 errors:
Quote:
test.cpp(28) : error C2109: subscript requires array or pointer type test.cpp(28) : error C2106: '=' : left operand must be l-value test.cpp(31) : error C2109: subscript requires array or pointer type
the 2D array isn't being recognized as being a 2D array it seems. anyone got a solution for this?

Share this post


Link to post
Share on other sites
Quote:
Original post by Shai

anyone got a solution for this?


I think so...

Essentially, I find it better to use one dimensional arrays and then use little functions or macros to index them as if they were 2d.

So, make it like this:


#include <iostream>
using namespace std;

class test
{
public:
int *p;

void allocate(int amount)
{
p = new int[amount*3];
}

test(int amount)
{
allocate(amount);
}
};

int main()
{
int number;
cin >> number;

test test1(number);

for(int i = 0; i < number; i++)
(test1.p)[(3*i)+1] = 1;

for(int j = -1; j < number+1; j++)
cout << test1.p[(j*3)+1] << endl;

return 0;
}

Share this post


Link to post
Share on other sites
You are leaking memory.

int (*p)[3] = new int[amount][3];

Declares a new pointer called p to int[3], it does not use the p inside the class, which is an int*.

The correct method would be to use


class test{

int (*p)[3];

void allocate(int amount)
{
p = new int[amount][3];
}

..
};

Share this post


Link to post
Share on other sites
Neither C nor C++ really support multidimensional arrays. You can either allocate a 'normal' 1D array and index it manually, or create an array of arrays. Furthermore, a pointer is always seen as a unidimensional array, so with int *p; you can never write p[a][b].

All things considered, you really just should use a std::vector<int> and write vec[x+y*row_size] instead of vec[y][x].

Or use boost::multi_array.

Edit: Jingo, your code is an utter abomination.

p[0] = new int[amount];
p[1] = new int[amount];
p[2] = new int[amount];

would be correct, but even then, would result on a 3xN array of arrays, not a Nx3 bidimensional array.


And of course, if you ever call allocate() twice... you'll still leak memory.

[Edited by - Fruny on January 1, 2005 1:17:15 PM]

Share this post


Link to post
Share on other sites
i agree with Frunny. Rather then deal with trying to hack my way to getting a dynamic 2d array i just have a class that contains a 1d array but you access it, modify it and resize it just like a 2d array so that way you have the orginization of a 2d and the flexablity of a 1d

also

p[0] = new int[amount];
p[1] = new int[amount];
p[2] = new int[amount];

this will create array filled with garbage so you would have to go through and zero out each segment if your not sure if your going to use all of the array otherwise you could get some wierd results

reason: new calls the int constructor in that case witch dosnt exist so it just fills it with meaning-less garabage (numbers like 1820043882)

Share this post


Link to post
Share on other sites
Quote:
Original post by Fruny

Edit: Jingo, your code is an great utter abomination.


Thanks! :)

Edit by Fruny: You're welcome.

You cut half of my post off Fruny! tut tut

other half:

Plus the code is not really a hack in any shape or form. It is even used as an example in the standard, 5.3.4.5 if you are interested. :)

Edit by Fruny: Fine, I retract my objection.

Share this post


Link to post
Share on other sites

#include <iostream>
#include <vector>

template<class T>
class Array2D
{
size_t m_rows;
size_t m_cols;
std::vector<T> m_data;
public:
Array2D(size_t rows, size_t cols)
: m_rows(rows), m_cols(cols), m_data(rows*cols)
{}

T* operator[](size_t idx) { return &m_data[idx*m_cols]; }
const T* operator[](size_t idx) const { return &m_data[idx*m_cols]; }
};

int main()
{
int number;
cin >> number;

Array2D<int> test1(number, 3);

for(int i = 0; i < number; i++)
test1[i][1] = 1;

for(int j = -1; j < number+1; j++)
std::cout << test1[j][1] << std::endl;

return 0;
}

Share this post


Link to post
Share on other sites
Quote:
Original post by Jingo
int j = -1;

??

errm... :)

I had a reason for putting that there, but I forgot what it was :p

Share this post


Link to post
Share on other sites
Any reason you don't have a color stuct?

struct Color {
unsigned char a;
unsigned char r;
unsigned char g;
unsigned char b;
}

Then you can simply make a linear array of these and be done with it. Be carefull of the component order though, depending on what you're doing you may have to compensate for Windows' Wackyness(tm).

Also, if you want RGB to fit in exactly 24-bits you'll have to make sure you're at the proper PACK setting, and in which case you should be aware that you'll probably take a performance penalty for having unaligned data.

Good luck.

Share this post


Link to post
Share on other sites

This topic is 4729 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this