I want to declare a pyramid like structure in C++ in a particular way but cannot - c++

I am essentially trying to declare something like this but I am unable to because of "too many initializer variables".
int** a = { {1},{2,3},{3,4,5} };
As a side question, if this were to work with some slight modification would it have the size of 9 (3x3) or 6 (1+2+3)?
I can implement this behavior with vectors such as the following, but I am curious as to why can't I do it more directly.
vector<int*>a = vector<int*>();
for (int i = 0; i < 20; i++)
{
a.push_back(new int[i]);
for (int j = 0; j <= i; j++)
a[i][j] = i+j;
}

Using a double pointer in C++ statically has a different memory arrangement than using new dynamically. The difference is that a static ** takes continuous memory automatically at compile time, where a dynamic one will not. Static multidimensional arrays are stored continuously, as discussed here.
Related: my question here.
Since your array cannot be stored continuously, it cannot be declared statically.

Related

C++ : How to safely deallocate a heap-allocated array of vectors?

I am currently working with code that at the moment requires me to make an array of vectors (I am new to C++ - if this is an absolutely terrible idea, I would greatly appreciate the feedback).
Let's say I allocate memory on the heap for my vectors like so:
#include <iostream>
#include <vector>
#include <random>
int main() {
typedef std::vector<double> doubleVec;
long N = 1000;
long M = 1000;
doubleVec *array = new doubleVec[N];
for (long i = 0; i < N; i++) {
doubleVec currentVec = array[i];
currentVec.resize(M);
for (long j = 0; j < M; j++)
currentVec[j] = std::rand();
}
// ... do something with the data structure
delete [] array;
}
When I've done everything I need to do with the data, how should I safely deallocate this data structure?
NOTE: There were other things I did wrong in my inital post that I didn't intend to be the focus of the discussion (uninitialized variables, didn't resize vectors, etc). I fixed those now. Thank you all for pointing those out.
f this is an absolutely terrible idea, I would greatly appreciate the feedback).
Yes, this is a terribly bad idea. To be specific, owning bare pointers are a bad idea. Instead of manually allocating a dynamic array, it is usually better to use a container such as std::vector.
How to safely deallocate a heap-allocated array of vectors?
By using a vector instead of manual dynamic array. In this case, a simple solution is to use a vector of vectors.
A potentially better solution would be to allocate a single flat vector of doubles of size 1000*1000 where elements of each "subvector" is after another. This requires a bit of simple math to calculate the index of the sub vectors, but is in most use cases faster.
Other notes:
typedef std::vector<double> doubleVec;
Avoid obfuscating the program by hiding type names like this.
for (long j; j < M; j++)
^^^^^^
You leave this variable uninitialised. When the indeterminate value is used later, the behaviour of the program is undefined.
Furthermore, you forgot to include the standard headers which define std::vector and std::rand.
I got a seg fault
See the other answer regarding you not actually adding any elements to the vectors that are in the array. This, and the uninitialised variables are the most likely reason for your segfault depending on what "do something" does.
The problem is not in deallocating but in each vector allocation. Where in your code do you use the M value (except while accessing the elements)? There are other problems in your code, so the quick fix is:
for (long i; i < N; i++) {
doubleVec &currentVec = array[i];
currentVec.resize(M);
for (long j; j < M; j++)
currentVec[j] = std::rand();
}
Pay special attention that currentVec is a reference: otherwise no changes would be stored in the array.
Anyway, the main question everybody would have is: why do you need to have an array of vectors?.. The vector of vectors is a much more elegant solution.
Update: I've missed the fact that you have forgotten to initialize both i and j. In addition to the advice to initialize them I would recommend to use the auto keyword that would make it impossible to leave the variable uninitialized:
for (auto i=0UL; i < N; i++) {
doubleVec &currentVec = array[i];
currentVec.resize(M);
for (auto j=0UL; j < M; j++)
currentVec[j] = std::rand();
}
0UL means zero of the type unsigned long.

Dynamic 2D array without using new

I've been posed with creating a dynamic 2D array in C++ without using new in C++. I have been trying for a while to make something work but I'm clueless as to what I'm supposed to do.
Edit: Sorry, should have been more specific. Just to be transparent, yes it is homework, and no I don't want it solved I just want to be pointed (no pun intended) in the right direction to code it myself.
The order, for reference, is as follow: Develop a console application to create a type int matrix of size m x n using pointers. The user must input the values for the size of the matrix from the keyboard and its contents must be randomly generated (1 - 100). Then, the transpose of the matrix must be calculated and shown (it's necessary to create classes).
We can't use new, nor vector, as we have to do it just via pointers with uni-dimensional arrays. So far I created a class that represent the "rows", and another class which represents the "columns". The columns go into the rows and the rows go into another class called matrix. That was the idea but was having trouble implementing it.
new is the only way to create dynamic objects or arrays in standard C++. So, depending on how you interpret the task, it could be considered impossible.
If we assume that it is OK for you to call a standard function that internally calls new, then the problem is solvable. A commonly used way to create a dynamic array in C++ is to use std::vector. Elements of std::vector may not be arrays however, so a 2D dynamic array is not technically possible using it. One workaround is to wrap the array within a class, and use the class as element of the vector. There is a standard template for such array wrapper: std::array. An example of a vector of array wrappers:
std::vector<std::array<type_of_element, 10>> name_of_vector(number_of_arrays);
The elements of the arrays within the dynamic array managed by the vector will have effectively the same layout as a 2D array would.
malloc did the trick. Here is the code I used to test it. It was a bit convoluted to figure out how to write the matrix loop but once I got it down I realized how obvious it was.
Matriz::Matriz(int numFil, int numCol)
:numFil(numFil), numCol(numCol)
{
mat = (int *)malloc(numFil * numCol * sizeof (int));
int c = 0;
for(int i = 0; i < numFil; i++)
{
for(int j = 0; j < numCol; j++)
{
*(mat + i * numCol + j) = ++c;
}
}
}
void Matriz::printMat()
{
for(int i = 0; i < numFil; i++)
{
for(int j = 0; j < numCol; j++)
{
std::cout << *(mat + i*numCol + j);
}
std::cout << std::endl;
}
}

Should I use matrix[][max] or **matrix in C++?

I think it will be very easy when I do it with this:
int n = 4;
int matrix[n][n];
rather then:
p = new int *[n];
for (int i = 0; i < n; i++)
p[i] = new int [n];
So, Which is better? When do we use ** to create a matrix or a array?
int n = 4;
int matrix[n][n];
Your first example isn't c++ standard conform, the standard doesn't support variable length arrays.
int** p = new int *[n];
for (int i = 0; i < n; i++)
p[i] = new int [n];
For your second example you should better use a std::vector<int> instead and organize matrix rows and columns as sections in the vector:
int n = 4;
std::vector<int> matrix(n*n);
Using new and delete yourself is usually not necessary in C++ and peppered with pitfalls and obstacles, which are taken care of in the appropriate standard library container and smart pointer classes.
First declaration is non-standard: n must be known at compile time in order for the code to compile. Some compilers offer variable-length arrays as an extension, but the code remains non-standard.
The standard approach to situations when you need a matrix in C++ is to use std::vector<std::vector<T>> for situations when the size is not known until the runtime. When the size is known at compile time and you prefer allocation in automatic area, use std::array<N,std::array<N,T>> instead of vectors.
Both these approaches let you construct objects that behave exactly like arrays of arrays, but you don't need to manage their memory explicitly.

Why can't a multidimensional array be allocated with one new call in C++?

In C++ you can easily allocate one dimensional array like this:
T *array=new T[N];
And you can delete it with one statement too:
delete[] array;
The compiler will know the magic how to deallocate the correct number of bytes.
But why can't you alloc 2-dimensional arrays like this?
T *array=new T[N,M];
Or even like this?
T *array=new T[N,M,L];
If you want a multidimensional you have to do it like this:
T **array=new T*[N];
for(int i=0;i<N;i++) array[i]=new T[M];
If you want a fast program that uses matrices (matrix operations, eigenvalue algorithms, etc...) you might want to utilize the cache too for top performance and this requires the data to be in the same place. Using vector<vector<T> > is the same situation. In C you can use variable length arrays on the stack, but you can't allocate them on the heap (and stack space is quite limited), you can do variable length arrays in C++ too, but they won't be present in C++0x.
The only workaround is quite hackish and error-phrone:
T *array=new T[N*M];
for(int i=0;i<N;i++)
for(int j=0;j<M;j++)
{
T[i*N+j]=...;
}
Your workaround of doing T *array=new T[N*M]; is the closest you can get to a true multi-dimensional array. Notice that to locate the elements in this array, you need the value of M (I believe your example is wrong, it should be T[i*M+j]) which is known only at run-time.
When you allocate a 2D array at compile-time, say array[5][10], the value 10 is a constant, so the compiler simply generates code to compute i*10+j. But if you did new T[N,M], the expression i*M+j depends on the value of M at the time the array was allocated. The compiler would need some way to store the value of M along with the actual array itself, and things are only going to get messy from here. I guess this is why they decided not to include such a feature in the language.
As for your workaround, you can always make it less "hackish" by writing a wrapper class that overloads operator (), so that you could do something like array(i, j) = ....
Because multidimensional array is something different then array of arrays/pointers.
use std::vector
Why can't a multidimensional array be allocated with one new call in C++?
Because when the ISO wrote the C++ language standard, they didn't decide to add that feature to the language. I don't know why they decided not to.
If you don't like that, you can create helper functions to allocate/free multidimensional arrays, or you can switch to a language like C# or Java that does support easily allocating multidimensional arrays.
What you can do, however, is allocate an object containing a two-dimensional array off the heap. I would just write a wrapper class for it.
I was thinking about this question last night, and this solution came to me.
T * raw = new T[N*M];
T ** array = new T*[N];
for(int i=0; i<N; i++)
array[i] = raw + i * M;
Now "array" acts just like a contiguous static sized two dimensional array. You just have to take care of deleting both the raw array, and the multi-dimensional array.
I would recommend that you use a Boost::multi_array, from the library of the same name, which provides a simple interface to a multidimensional array. It can be allocated in one line, and at a sufficiently high optimization level is usually as fast as a native array.
Here's some example code from the library's website:
#include "boost/multi_array.hpp"
#include <cassert>
int
main () {
// Create a 3D array that is 3 x 4 x 2
typedef boost::multi_array<double, 3> array_type;
typedef array_type::index index;
array_type A(boost::extents[3][4][2]);
// Assign values to the elements
int values = 0;
for(index i = 0; i != 3; ++i)
for(index j = 0; j != 4; ++j)
for(index k = 0; k != 2; ++k)
A[i][j][k] = values++;
// Verify values
int verify = 0;
for(index i = 0; i != 3; ++i)
for(index j = 0; j != 4; ++j)
for(index k = 0; k != 2; ++k)
assert(A[i][j][k] == verify++);
return 0;
}
Because the comma is an operator.
int a = (3, 5, 7, 9);
The program will evaluate 3, discard the result,
evaluate 5, discard the result,
evaluate 7, discard the result,
evaluate 9, and assign it to a.
Hence the syntax you are looking for can't be use,
and retain backward compatibility to c.

C++ 2DArray Objects; Pointers and Array Problems

This problem is from a solved problem in my old question, which is from:
C++ Inserting 2D array Object into another 2D array Object
But also created a new problem for me. Please read the question and the solution in the link to understand my problem. The solution in the previous question was to make my Data Member Function into a pointer to pointer, to allow the pass into the other Data Member Function. But while fixing that, the first Data Member Function which is smallerArray.extractPiece() now only return address of the pointer to the pointer and not the content of those pointers. I need the content in order for my 2nd Data Member Function largerArray.extractArray(result) to work properly, as I attempt run the code and gave an Window Error, and not a Compile Error.
Does anyone know how to extract the content of the smallerArray.extractPiece() and instead of getting of the address, and is there isn't, does anyone have any other methods of creating a 2D-Array Object?
void Grid::extractArray( int** arr )
{
for(int i = 0; i < xGrid ; ++i) {
for (int j = 0; j < yGrid ; ++j) {
squares[i][j] = arr[i][j];
}
}
}
The smaller array int**arr does not have as many elements as the Grid.
xGrid and yGrid are too large to use as indices for arr[][].
You must pass the complete smaller array object into the extractArray() function and use the sizes from this object for the copy function.
void Grid::extractArray( const Piece & piece)
{
for(int i = 0; i < piece.xGrid ; ++i) {
for (int j = 0; j < piece.yGrid ; ++j) {
squares[i][j] = arr[i][j];
}
}
}
Right now, your problem seems a bit underspecified. How large of a 'piece' do you expect from the smaller array, and where in the larger array do you want to insert it?
It may make things easier if you create a 2D array object or class (or struct)
class BaxMatrix {
public:
int m_Data[4][4];
}
with a little work you could build dynamic structures or use STL structures as desired.
The data, and the reference to the data are two different animals. It's best for you to clarify each of their roles in your thinking, before proceeding forward.