В Java все находится в форме класса.
Если вы хотите использовать любой объект, тогда у вас есть две фазы:
Пример:
Object a;
a=new Object();
То же самое для концепции массива
Item i[]=new Item[5];
i[0]=new Item();
Если вы не дают секцию инициализации, тогда возникает NullpointerException
.
Вам нужны приблизительно 2,5 megs, поэтому просто использование "кучи" должно быть прекрасным. Вам не нужен вектор, если Вы не должны изменять размер его. Посмотрите C++ FAQ, Облегченный для примера использования "2D" массива "кучи".
int *array = new int[800*800];
(Не забывайте delete[]
это, когда Вы сделаны.)
Пример Kevin хорош, однако:
std::vector<T> buffer[width * height];
Должен быть
std::vector<T> buffer;
При расширении его немного Вы могли, конечно, добавить перегрузки оператора вместо в () - функции:
const T &operator()(int x, int y) const
{
return buffer[y * width + x];
}
и
T &operator()(int x, int y)
{
return buffer[y * width + x];
}
Пример:
int main()
{
Array2D<int, 800, 800> a;
a(10, 10) = 50;
std::cout << "A(10, 10)=" << a(10, 10) << std::endl;
return 0;
}
Вы могли сделать вектор векторов, но это будет иметь немного служебными. Для z-буфера более типичный метод должен был бы создать массив размера 800*800=640000.
const int width = 800;
const int height = 800;
unsigned int* z_buffer = new unsigned int[width*height];
Затем получите доступ к пикселям следующим образом:
unsigned int z = z_buffer[y*width+x];
Каждое сообщение до сих пор оставляет управление памятью для программиста. Это может и должно избежаться. ReaperUnreal является штопкой близко к тому, что я сделал бы, кроме я буду использовать вектор, а не массив и также заставлять размеры обработать параметры по шаблону и изменить функции доступа - и о просто IMNSHO очищают вещи немного:
template <class T, size_t W, size_t H>
class Array2D
{
public:
const int width = W;
const int height = H;
typedef typename T type;
Array2D()
: buffer(width*height)
{
}
inline type& at(unsigned int x, unsigned int y)
{
return buffer[y*width + x];
}
inline const type& at(unsigned int x, unsigned int y) const
{
return buffer[y*width + x];
}
private:
std::vector<T> buffer;
};
Теперь можно выделить этот 2-D массив на стеке очень хорошо:
void foo()
{
Array2D<int, 800, 800> zbuffer;
// Do something with zbuffer...
}
Я надеюсь, что это помогает!
Править: Удаленная спецификация массива от Array2D::buffer
. Благодаря Andreas для ловли этого!
Я мог бы создать единственный массив размера 800*800. Вероятно, более эффективно использовать единственное выделение как это, вместо того, чтобы выделить 800 отдельных векторов.
int *ary=new int[800*800];
Затем, вероятно, инкапсулируйте это в классе, который действовал как 2D массив.
class _2DArray
{
public:
int *operator[](const size_t &idx)
{
return &ary[idx*800];
}
const int *operator[](const size_t &idx) const
{
return &ary[idx*800];
}
};
Абстракция, показанная здесь, имеет много дыр, например, что происходит, если Вы получаете доступ мимо конца "строки"? Книга "Эффективный C++" имеет довольно хорошее обсуждение записи хороших многомерных массивов в C++.
Одна вещь, которую можно сделать, изменить размер стека (если Вы действительно хотите массив на стеке) с VC флаг, чтобы сделать, это [/F] (http://msdn.microsoft.com/en-us/library/tdkhxaks (По сравнению с 80) .aspx).
Но решение, которое Вы, вероятно, хотите, состоит в том, чтобы поместить память в "кучу", а не на стеке, для которого необходимо использовать a vector
из vectors
.
Следующая строка объявляет a vector
из 800 элементов каждый элемент является a vector
из 800 int
s и сохраняет Вас от управления памятью вручную.
std::vector<std::vector<int> > arr(800, std::vector<int>(800));
Отметьте пространство между этими двумя закрывающими угловыми скобками (> >
) который требуется в порядке, снимают неоднозначность его от оператора права сдвига (который больше не будет необходим в C++ 0x).
Или Вы могли попробовать что-то как:
boost::shared_array<int> zbuffer(new int[width*height]);
Необходимо все еще смочь сделать это также:
++zbuffer[0];
Больше никакого беспокойства об управлении памятью, никакие пользовательские классы для заботы о, и легко бросить вокруг.
Существует C как способ сделать:
const int xwidth = 800;
const int ywidth = 800;
int* array = (int*) new int[xwidth * ywidth];
// Check array is not NULL here and handle the allocation error if it is
// Then do stuff with the array, such as zero initialize it
for(int x = 0; x < xwidth; ++x)
{
for(int y = 0; y < ywidth; ++y)
{
array[y * xwidth + x] = 0;
}
}
// Just use array[y * xwidth + x] when you want to access your class.
// When you're done with it, free the memory you allocated with
delete[] array;
Вы могли инкапсулировать y * xwidth + x
в классе с легким добираются и метод установки (возможно с перегрузкой []
оператор, если Вы хотите начать входить в более усовершенствованный C++). Я рекомендовал бы добраться до этого медленно хотя, если Вы только запускаете с C++ и не начинаете создавать допускающие повторное использование полностью шаблоны классов для массивов n-размера, которые просто смутят Вас, когда Вы начнетесь.
Как только Вы входите в графическую работу, Вы могли бы найти, что издержки наличия дополнительных вызовов класса могли бы замедлить Ваш код. Однако не волнуйтесь об этом, пока Ваше приложение не достаточно быстро, и можно представить его для показа, где время потеряно, вместо того, чтобы делать более трудным использовать в запуске с возможной ненужной сложностью.
Я нашел, что C++ облегченный FAQ был большим для получения информации, такой как это. В особенности Вашим вопросом отвечают:
http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.16
Можно выделить массив на статическом устройстве хранения данных (в объеме файла или добавить static
спецификатор в функциональном объеме), если Вам нужен только один экземпляр.
int array[800][800];
void fn()
{
static int array[800][800];
}
Таким образом, это не перейдет к стеку, и не необходимо иметь дело с динамической памятью.
Ну, основываясь на том, что запущенный Niall Ryan, если производительность является проблемой, можно взять этот шаг вперед путем оптимизации математики и инкапсуляции этого в класс.
Таким образом, мы запустим с небольшого количества математики. Вспомните, что 800 может быть записан в полномочиях 2 как:
800 = 512 + 256 + 32 = 2^5 + 2^8 + 2^9
Таким образом, мы можем записать нашу функцию обращения как:
int index = y << 9 + y << 8 + y << 5 + x;
Таким образом, если мы инкапсулируем все в хороший класс, мы добираемся:
class ZBuffer
{
public:
const int width = 800;
const int height = 800;
ZBuffer()
{
for(unsigned int i = 0, *pBuff = zbuff; i < width * height; i++, pBuff++)
*pBuff = 0;
}
inline unsigned int getZAt(unsigned int x, unsigned int y)
{
return *(zbuff + y << 9 + y << 8 + y << 5 + x);
}
inline unsigned int setZAt(unsigned int x, unsigned int y, unsigned int z)
{
*(zbuff + y << 9 + y << 8 + y << 5 + x) = z;
}
private:
unsigned int zbuff[width * height];
};