I'm just learning about C++. I'm doing practice with initialize list, so I made a class like this
class Matrix
{
public:
const int x_size;
const int y_size;
int *data;
Matrix(int _x_size, int _y_size) : x_size(_x_size), y_size(_y_size)
{
data = new int[y_size][x_size];
}
~Matrix()
{
delete[][] data;
}
};
int main(void)
{
Matrix A = Matrix(10, 10);
return 0;
}
And compiler said as: array size in operator new must be constant.
So I searched and someone said, these are not 'compiler time constant'.
But it is obvious that I can't use that size as macros in here...
Then. How should I get proper-sized array with Constructor?
If you are just learning c++ then the best tip is stay away from memory management. Use the stl types if you can. Use a std::vector to replace that array:
std::vector<std::vector<int>> data;
create it like this:
data(y_size, std::vector<int>(x_size, 0));
and access it like this:
data[i][j];
As jaunchopanza said, you can also use a 1D array which might be better. You would create and edit it in similar ways:
std::vector<int> data;
data(y_size * x_size, 0);
data[y_size*i + j];
The advantage is that it is faster for accessing, especially if x_size and y_size are going to be large. There is also an advantage in that the vector of vectors may be stored all over the place, as in each row(or column) will be in different places in memory. If you intend to get data that overlaps more than one row (or column) then it would be better to use the 1D array for speed.
You can Find more info here:
http://en.cppreference.com/w/cpp/container/vector
If you want to turn this into a matrix and do math etc. Than I would highly recomend Eigen it is by far the best matrix library: http://eigen.tuxfamily.org/index.php?title=Main_Page
you should write sth like this ( although it is not exception safe)
class Matrix
{
public:
const int x_size;
const int y_size;
int ** data;
Matrix(int _x_size, int _y_size) : x_size(_x_size), y_size(_y_size)
{
data = new int* [y_size];
for(int i =0 ; i < y_size ; i++)
{
data[i] = new int[x_size] ;
}
}
~Matrix()
{
for(int i= 0 ; i < y_size ; i++)
{
delete [] data[i];
}
delete[] data;
}
};
Related
I have declared a 2D array in C++ using pointers.
int **matrix = new int*[5];
for(int i=0;i<5;i++)
{
matrix[i] = new int[5];
}
Now as i have allocated memory to array 'matrix', Wondering how can i initialize all the array items in this format:
int arr[2][5] =
{
{1,8,12,20,25},
{5,9,13,24,26}
};
You should use a std::vector instead of new[]. If your compiler supports it (the newer ones do), you can use an initializer list.
std::vector<std::vector<int>> matrix = { { 1, 2, 3 }, { 4, 5 } };
Method suggested by you works only for fixed size arrays and not dynamic arrays.
You need to initialize them by yourself(read from file, use loops etc). Or if you are sure about array dimension, use 2D array instead of dynamically allocating it.
Or you can use C++11.
In C++11 you can use uniform initialization with operator new[]. For example:
auto arr = new int[2][5] {
{1,8,12,20,25},
{5,9,13,24,26}
};
Working on Clang 3.4
The simplest way is to use nested std::vector(s) and an initializer_list.
Dynamically allocated multidimensional array are quite error prone.
E.g. if you look closely at your example you'll see that the correct code for a [2][5] matrix is:
int **matrix = new int*[2];
for(int i(0); i < 2; ++i)
matrix[i] = new int[5];
If you really want a matrix, probably neither std::vector<std::vector<int>> nor int** matrix are good layouts (the main problem is that you lose data locality).
A classic solution that works quite nicely is a wrapper around a single vector, that keeps track of the "shape" of the matrix being represented and provides an operator to access the data:
class matrix
{
public:
matrix(unsigned rows, unsigned columns)
: columns_(columns), data_(columns * rows)
{}
matrix(std::initializer_list<std::initializer_list<int>> lst)
: matrix(lst.size(), lst.size() ? lst.begin()->size() : 0)
{
unsigned i(0), j(0);
for (const auto &l : lst)
{
for (const auto &v : l)
{
operator()(i, j) = v;
++j;
}
j = 0;
++i;
}
}
int &operator()(unsigned row, unsigned column)
{ return data_[row * columns_ + column]; }
private:
unsigned columns_;
std::vector<int> data_;
};
and you can write:
matrix m = {
{1,8,12,20,25},
{5,9,13,24,26},
};
I'm developing a 2d-platformer. Everything was fine until I've got some hard to solve problem. Level map is stored in dynamic multidemension array(char **map). It works fine, until I want to redefine it
Here's the part of code:
Map& Map::operator=(const Map& rhs)
{
if(width!=0||height!=0)
{
for(int i=0;i<width;i++)
delete[] map[i];
delete[] map;
} //deleting previously created array
height=rhs.height;
width=rhs.width; //receiving other map's size
map=new char* [width];
walkmap=new unsigned char* [width];
objmap=new char* [width];
for(int i=0;i<width;i++)
{
*(map+i)=new char[height];
} //creating new array
for(int h=0;h<height;h++)
for(int w=0;w<width;w++)
{
map[w][h]=rhs.map[w][h];
} //receiving new values
//...
}
Everything works fine for the first time, but when I need to redefine array for the second time my program crashes at the part, when array is receiving new values from another one. May be I miss something, but I can't find it! I was searching for this problem, but didn't find what I am doing wrong. Help me, please.
As always, Boost has an elegant and memory efficient multi-dimensional array class:
http://www.boost.org/doc/libs/1_39_0/libs/multi_array/doc/user.html
For example, to setup a 10 x 20 array of bool values:
boost::multi_array mtaFlagMatrix(boost::extents[10][20]);
Then to access its elements:
mtaFlagMatrix[2][6] = false; // indexes are zero-based - just like normal C arrays
...
if ( mtaFlagMatrix[2][6] )
{
...
}
Then, you can resize the array this way (existing values are preserved):
typedef boost::multi_array array_type;
array_type::extent_gen extents;
array_type A(extents[3][3][3]);
A[0][0][0] = 4;
A[2][2][2] = 5;
A.resize(extents[2][3][4]);
assert(A[0][0][0] == 4);
// A[2][2][2] is no longer valid.
This saved me a lot of time testing for extreme cases.
Your 2d array is not freeed properly. I advise you to use the Iliffe way of allocating 2d arrays which is faster and safer to use:
char** alloc_array( int h, int w )
{
typedef char* cptr;
int i;
char** m = new cptr[h];
m[0] = new char[h*w];
for(i=1;i<h;i++) m[i] = m[i-1]+w;
return m;
}
void release_array(char** m)
{
delete[] m[0];
delete[] m;
}
int main()
{
int r,c;
char** tab;
int width = 5;
int height = 3;
tab = alloc_array(height, width); /* column first */
for(r = 0;r<height;++r)
for(c = 0;c<width;++c)
tab[r][c] = (1+r+c);
for(r = 0;r<height;++r)
{
for(c = 0;c<width;++c)
{
printf("%d\t",tab[r][c]);
}
puts("");
}
release_array(tab);
}
This can be easily encapsulated in a neat 2d-array class or made to use std::vector instead of raw allocation. Prefer this way of doing 2d array as it is cache friendly , style provide the [][] access and is no slower and soemtimes faster than the polynomial 1d access.
int java declaration of array like this
int a[][]=new int[3][3] works but in c++ not why? please help me i have not used c++ a long time so please help me
In C++ you would just say int a[3][3];. C++ doesn't require all arrays and objects to be declared with new.
EDIT:
For a dynamic size n you can't use stack based arrays.
Probably the best way is a vector of vectors:
std::vector<std::vector<int> > a;
a.resize(n);
for(int i = 0; i < n; ++i)
{
a[i].resize(n);
}
Generally speaking, you should avoid using arrays in C++ at all. While there are special cases where they're (nearly) the only choice, your first choice should generally be to use a std::vector instead. In this case, what you want becomes fairly straightforward:
// vector of 3 ints, each initialized to 0
std::vector<int> init(3, 0);
// vector of three vectors of int, each initialized to the value of 'init':
std::vector<std::vector<int> > a(3, init);
In C++ you can allocate arrays on the stack or on the heap. Allocation on stack is only possible for fixed-size arrays (i.e. the sizes are known at compile time):
int a[3][3];
The above allocates a 3x3 array on the stack. If you want to dynamically allocate arrays (i.e. the size is not know at compile time), it has to be done on the heap. To my knowledge however, C++ does not directly support multydimensional arrays. So you may have to do something like
int * a = new int[n*n];
And then access an element at (i,j) as a[i + j * n].
Alternatively you can also something like
int **a = new *int[n];
for(int i = 0; i < n; ++i {
a[i] = new int[n];
}
Trying to allocate a dynamic array on the stack such as
int a[n][n];
Will result in a compiler error.
In C++ you can declare a 2-dimensional int-array of a predetermined size using int a[30][10];.
You can allocate new arrays with new in Java because arrays are Objects ant thus they have to be created using new in Java. But C++ does not force you to create everything using new.
Of course, it would be no problem to introduce these new syntax for declaring arrays also in C++, but why introduce a new syntax, if "everybody" is used to the existing one?
Note that you can not declare a 2-dimensional array with sizes determined at runtime using int arr[n][m]. You have to create an array of arrays representing a 2-dimensional array using int **arr = new int[n][m] i.e. in C++ an array of pointers pointing to each subarray. Analoguesly for higher dimensional arrays.
Another way for multidimensional arrays is to declare just a 1-dimensional array and compute the indices accordingly. However, this involves some thoughts on how to organize data.
The closest match is this:
int a[][] = {
new int[3],
new int[3],
new int[3]
};
with memory management being your responsibility in C++ (unless you're using a non-standard custom new[]) -- this means you will have to call delete[] for each of elements of a.
It's best to declare it this way, though:
int a[3][3];
This will create an automatic 3x3 two-dimensional array. Unlike the first example, its memory will be allocated on the stack and thus will be deleted automatically. No need to call delete on this one.
This topic deals with two important aspects of C++: explicit pointers and dynamic memory. The short answer is that, in C++, all two need to do to initialize an array is declare it, like so:
int a [5][5];
If you want to use a variable for the array size, it must be a const int:
const int n = 5;
int b [n];
Be aware, however, that much of the functionality of arrays in Java does not exist in C++. For example, there is no straightforward "length" attribute.
The long answer is, look up the two topics addressed above, in particular in terms of arrays and the "new" keyword, as well as the "const" keyword. Understanding these ideas is vital to using C++;
I once had this same problem and ended up creating a class for it. Basically it's stored as a pointer of single dimension array and the pointers are manipulated a bit so that it acts just like a 2D array (matrix). Here's the code I used:
#include <utility>
#include <memory.h>
template <typename T>
class Matrix
{
protected:
T** m;
int x,y;
__forceinline void setMatrix()
{
assert(x > 0);
assert(y > 0);
m = new T*[y];
m[0] = new T[x*y];
for (int i = 1; i < y; ++i)
{
m[i] = m[i-1] + x;
}
}
public:
Matrix():m(0),x(0),y(0){}
Matrix(int rows, int cols):x(cols),y(rows),m(0)
{
setMatrix();
}
Matrix(const Matrix<T>& mat):m(0),x(mat.x),y(mat.y)
{
setMatrix();
memcpy_s(m[0], x*y, mat.m[0], x*y);
}
~Matrix()
{
if (m)
{
delete[] m[0];
delete[] m;
}
}
void fill(const T& val)
{
if (m)
{
for (int j = 0; j < y; ++j)
for (int i = 0; i < x; ++i)
m[j][i] = val;
}
}
T& at(int row, int col)
{
assert(row >= 0 && row < y);
assert(col >= 0 && col < x);
return m[row][col];
}
const T& at(int row, int col) const
{
assert(row >= 0 && row < y);
assert(col >= 0 && col < x);
return m[row][col];
}
T* operator[](int row)
{
assert(row >= 0 && row < y);
return m[row];
}
const T* operator[](int row) const
{
assert(row >= 0 && row < y);
m[row];
}
T& operator ()(int row, int col)
{
assert(row >= 0 && row < y);
assert(col >= 0 && col < x);
return m[row][col];
}
const T& operator ()(int row, int col) const
{
assert(row >= 0 && row < y);
assert(col >= 0 && col < x);
return m[row][col];
}
void swap(Matrix<T>& mat)
{
std::swap(m, mat.m);
std::swap(x, mat.x);
std::swap(y, mat.y);
}
const Matrix& operator = (const Matrix<T>& rhs)
{
Matrix temp(rhs);
swap(temp);
return *this;
}
//
int getRows() const
{
return y;
}
int getColumns() const
{
return x;
}
};
Usage would be like:
typedef Matrix<int> IntMatrix;
IntMatrix mat(2,3); // Creates a 2x3 matrix to store integers.
mat.fill(0); // Fill it with zeroes.
int val02 = mat[0][2]; // Unsafe way to retrieve values
int val12 = mat(1,2); // Safe way to retrieve values;
mat(0,1) = 10; // Assign values directly to the matrix.
You can also extend this class so that it has other matrix related function in it.
In C++ I'd like to do something like:
int n = get_int_from_user();
char* matrix = new char[n][n];
matrix[0][0] = 'c';
//...
matrix[n][n] = 'a';
delete [][] matrix;
but of course this doesn't work. What is the best way to do something similar? I've seen some solutions to this but they seem pretty messy.
The manual dynamic way:
Let's say you want an array of width*height, the most efficient way is to just use a single dimensional array:
char *matrix = new char[width*height];
To delete it:
delete[] matrix;
To access it:
char getArrayValue(char *matrix, int row, int col)
{
return matrix[row + col*width];
}
To modify it:
void setArrayValue(char *matrix, int row, int col, char val)
{
matrix[row + col*width] = val;
}
Boost Matrix:
Consider using boost::matrix if you can have the dependency.
You could then tie into the boost linear algebra libraries.
Here is some sample code of boost::matrix:
#include <boost/numeric/ublas/matrix.hpp>
using namespace boost::numeric::ublas;
matrix<char> m (3, 3);
for (unsigned i = 0; i < m.size1 (); ++ i)
for (unsigned j = 0; j < m.size2 (); ++ j)
m (i, j) = 3 * i + j;
On the stack for some compilers:
Some compilers actually allow you to create arrays on the stack with runtime determined sizes. g++ is an example of such a compiler. You cannot do this by default VC++ though.
So in g++ this is valid code:
int width = 10;
int height = 10;
int matrix[width][height];
Drew Hall mentioned that this C99 feature is called Variable Length Arrays (VLAs) and it can probably be turned on in any modern compiler.
I usually do something like this:
char *matrix = new char [width * height];
matrix[i + j * width] = 'c'; // same as matrix[i][j] = 'c';
delete [] matrix;
You seem to be missing the whole point of C++ (C with classes) :-). This is the sort of use that's crying out for a class to implement it.
You could just use STL or other 3rd party class library which I'm sure would have the data structure you're looking for but, if you need to roll your own, just create a class with the following properties.
constructor which, given n, will just create a new n*n array of char (e.g., charray)..
member functions which get and set values based on x.y which simply refer to charray[x*n+y];
destructor which delete[]'s the array.
What about std::vector< std::vector<int> > array2d; ?
For a true two dimensional array:
int n = get_int_from_user();
char** matrix = new char*[n];
for (int i = 0; i < n; i++) {
matrix[i] = new char[n];
}
// Operations on matrix.
for (int i = 0; i < n; i++) {
delete [] matrix[i];
}
delete matrix;
Just off the top of my head. Mistakes, no doubt. However, other people have posted a more elegant approach, I think.
I like the 1-d array approach (the selected answer by Brian R. Bondy) with the extension that you wrap the data members into a class so that you don't need to keep track of the width separately:
class Matrix
{
int width;
int height;
char* data;
public:
Matrix();
Matrix(int width, int height);
~Matrix();
char getArrayValue(int row, int col);
void setArrayValue(int row, int col, char val);
}
The implementation is an exercise for the reader. ;)
I think this would be a good one.
int n = get_int_from_user();
char **matrix=new (char*)[n];
for(int i=0;i<n;i++)
matrix[i]=new char[n];
matrix[0][0] = 'c';
//...
matrix[n][n] = 'a';
for(int i=0;i<n;i++)
delete []matrix;
delete []matrix;
std::vector<int> m;
Then call m.resize() at runtime.
int* matrix = new int[w*h];
if you want to do something like Gaussian elimination your matrix should be
int** matrix = new int*[h];
for(size_t i(0); i < h; ++i)
matrix[i] = new int[w];
(in Gaussian elimination we usually need to exchange one row with another so it's better to swap pointers to rows in constant time rather than swapping by copying in linear time).
I would like to find out safe ways of implementing three dimensional arrays of integers in C++, using pointer arithmetic / dynamic memory allocation, or, alternatively using STL techniques such as vectors.
Essentially I want my integer array dimensions to look like:
[ x ][ y ][ z ]
x and y are in the range 20-6000
z is known and equals 4.
Have a look at the Boost multi-dimensional array library. Here's an example (adapted from the Boost documentation):
#include "boost/multi_array.hpp"
int main() {
// Create a 3D array that is 20 x 30 x 4
int x = 20;
int y = 30;
int z = 4;
typedef boost::multi_array<int, 3> array_type;
typedef array_type::index index;
array_type my_array(boost::extents[x][y][z]);
// Assign values to the elements
int values = 0;
for (index i = 0; i != x; ++i) {
for (index j = 0; j != y; ++j) {
for (index k = 0; k != z; ++k) {
my_array[i][j][k] = values++;
}
}
}
}
Each pair of square brackets is a dereferencing operation (when applied to a pointer). As an example, the following pairs of lines of code are equivalent:
x = myArray[4];
x = *(myArray+4);
x = myArray[2][7];
x = *((*(myArray+2))+7);
To use your suggested syntax you are simply dereferencing the value returned from the first dereference.
int*** myArray = (some allocation method, keep reading);
//
// All in one line:
int value = myArray[x][y][z];
//
// Separated to multiple steps:
int** deref1 = myArray[x];
int* deref2 = deref1[y];
int value = deref2[z];
To go about allocating this array, you simply need to recognise that you don't actually have a three-dimensional array of integers. You have an array of arrays of arrays of integers.
// Start by allocating an array for array of arrays
int*** myArray = new int**[X_MAXIMUM];
// Allocate an array for each element of the first array
for(int x = 0; x < X_MAXIMUM; ++x)
{
myArray[x] = new int*[Y_MAXIMUM];
// Allocate an array of integers for each element of this array
for(int y = 0; y < Y_MAXIMUM; ++y)
{
myArray[x][y] = new int[Z_MAXIMUM];
// Specify an initial value (if desired)
for(int z = 0; z < Z_MAXIMUM; ++z)
{
myArray[x][y][z] = -1;
}
}
}
Deallocating this array follows a similar process to allocating it:
for(int x = 0; x < X_MAXIMUM; ++x)
{
for(int y = 0; y < Y_MAXIMUM; ++y)
{
delete[] myArray[x][y];
}
delete[] myArray[x];
}
delete[] myArray;
Below is a straightforward way to create 3D arrays using C or C++ in one chunk of memory for each array. No need to use BOOST (even if it's nice), or to split allocation between lines with multiple indirection (this is quite bad as it usually gives big performance penalty when accessing data and it fragments memory).
The only thing to understand is that there is no such thing as multidimensional arrays, just arrays of arrays (of arrays). The innermost index being the farthest in memory.
#include <stdio.h>
#include <stdlib.h>
int main(){
{
// C Style Static 3D Arrays
int a[10][20][30];
a[9][19][29] = 10;
printf("a[9][19][29]=%d\n", a[9][19][29]);
}
{
// C Style dynamic 3D Arrays
int (*a)[20][30];
a = (int (*)[20][30])malloc(10*20*30*sizeof(int));
a[9][19][29] = 10;
printf("a[9][19][29]=%d\n", a[9][19][29]);
free(a);
}
{
// C++ Style dynamic 3D Arrays
int (*a)[20][30];
a = new int[10][20][30];
a[9][19][29] = 10;
printf("a[9][19][29]=%d\n", a[9][19][29]);
delete [] a;
}
}
For your actual problem, as there potentially is two unknown dimensions, there is a problem with my proposal at it allow only one unknown dimension. There is several ways to manage that.
The good news is that using variables now works with C, it is called variable length arrays. You look here for details.
int x = 100;
int y = 200;
int z = 30;
{
// C Style Static 3D Arrays
int a[x][y][z];
a[99][199][29] = 10;
printf("a[99][199][29]=%d\n", a[99][199][29]);
}
{
// C Style dynamic 3D Arrays
int (*a)[y][z];
a = (int (*)[y][z])malloc(x*y*z*sizeof(int));
a[99][199][29] = 10;
printf("a[99][199][29]=%d\n", a[99][199][29]);
free(a);
}
If using C++ the simplest way is probably to use operator overloading to stick with array syntax:
{
class ThreeDArray {
class InnerTwoDArray {
int * data;
size_t y;
size_t z;
public:
InnerTwoDArray(int * data, size_t y, size_t z)
: data(data), y(y), z(z) {}
public:
int * operator [](size_t y){ return data + y*z; }
};
int * data;
size_t x;
size_t y;
size_t z;
public:
ThreeDArray(size_t x, size_t y, size_t z) : x(x), y(y), z(z) {
data = (int*)malloc(x*y*z*sizeof data);
}
~ThreeDArray(){ free(data); }
InnerTwoDArray operator [](size_t x){
return InnerTwoDArray(data + x*y*z, y, z);
}
};
ThreeDArray a(x, y, z);
a[99][199][29] = 10;
printf("a[99][199][29]=%d\n", a[99][199][29]);
}
The above code has some indirection cost for accessing InnerTwoDArray (but a good compiler can probably optimize it away) but uses only one memory chunk for array allocated on heap. Which is usually the most efficient choice.
Obviously even if the above code is still simple and straightforward, STL or BOOST does it well, hence no need to reinvent the wheel. I still believe it is interesting to know it can be easily done.
With vectors:
std::vector< std::vector< std::vector< int > > > array3d;
Every element is accessible wit array3d[x][y][z] if the element was already added. (e.g. via push_back)
It should be noted that, for all intents and purposes, you are dealing with only a 2D array, because the third (and least significant) dimension is known.
Using the STL or Boost are quite good approaches if you don't know beforehand how many entries you will have in each dimension of the array, because they will give you dynamic memory allocation, and I recommend either of these approaches if your data set is to remain largely static, or if it to mostly only receive new entries and not many deletions.
However, if you know something about your dataset beforehand, such as roughly how many items in total will be stored, or if the arrays are to be sparsely populated, you might be better off using some kind of hash/bucket function, and use the XYZ indices as your key. In this case, assuming no more than 8192 (13 bits) entries per dimension, you could get by with a 40-bit (5-byte) key. Or, assuming there are always 4 x Z entries, you would simply use a 26-bit XY key. This is one of the more efficient trade-offs between speed, memory usage, and dynamic allocation.
There are many advantages to using the STL to manage your memory over using new/delete. The choice of how to represent your data depends on how you plan to use it. One suggestion would be a class that hides the implementation decision and provides three dimensional get/set methods to a one dimensional STL vector.
If you really believe you need to create a custom 3d vector type, investigate Boost first.
// a class that does something in 3 dimensions
class MySimpleClass
{
public:
MySimpleClass(const size_t inWidth, const size_t inHeight, const size_t inDepth) :
mWidth(inWidth), mHeight(inHeight), mDepth(inDepth)
{
mArray.resize(mWidth * mHeight * mDepth);
}
// inline for speed
int Get(const size_t inX, const size_t inY, const size_t inZ) {
return mArray[(inZ * mWidth * mHeight) + (mY * mWidth) + mX];
}
void Set(const size_t inX, const size_t inY, const size_t inZ, const int inVal) {
return mArray[(inZ * mWidth * mHeight) + (mY * mWidth) + mX];
}
// doing something uniform with the data is easier if it's not a vector of vectors
void DoSomething()
{
std::transform(mArray.begin(), mArray.end(), mArray.begin(), MyUnaryFunc);
}
private:
// dimensions of data
size_t mWidth;
size_t mHeight;
size_t mDepth;
// data buffer
std::vector< int > mArray;
};
Pieter's suggestion is good of course, but one thing you've to bear in mind is that in case of big arrays building it may be quite slow. Every time vector capacity changes, all the data has to be copied around ('n' vectors of vectors).