C++ multi dimensional array of pointers without declaration - c++

I want to declare multi dimensional (int his case two-dimensional) array. I can't declare size of global array. With one dimension, everything works:
#include <iostream>
#include <fstream>
using namespace std;
int N, M;
bool *table;
int main()
{
ifstream in ("in.txt");
in >> N >> M;
table = new bool[N];
return 0;
}
But if i want to declare two-dimensional array, I get an error:
'M' cannot appear in a constant-expression
#include <iostream>
#include <fstream>
using namespace std;
int N, M;
bool **table;
int main()
{
ifstream in ("in.txt");
in >> N >> M;
table = new bool[N][M];
return 0;
}
What is my option apart from declaring number instead of N and M, creating vector array or declaring table in main function?

What is my option apart from declaring number instead of N and M, creating vector array or declaring table in main function?
Allocate memory for N pointers.
For each pointer, allocate memory for M elements of type bool.
table = new bool*[N];
for (int i = 0; i < N; ++i )
{
table[i] = new bool[M];
}
When it's time to deallocate, use:
for (int i = 0; i < N; ++i )
{
delete [] table[i];
}
delete [] table;
You can avoid all the hassles of memory allocation and deallocation by using std::vector.
std::vector<std::vector<bool>> table(N, std::vector<bool>(M));

Use the old way of doing things: allocate a unidimensional array and afterwards access it by the unique index by doing the calculation (i*N+j). If you want to hide it create a function with two parameters for that.

If you want to avoid all the hassle of true multi-level arrays, you could:
int N=2, M=3;
bool *table = new bool[N*M];
// to access the element at (n,m):
ele = table[n*M + m];
This makes all the allocation/deallocation dead simple with the slight cost of having to type a bit more when accessing the elements. You could use a macro to fix that, of course.

Related

Qt not working when my array reach a certain size

For testing purposes, I'm trying different sizes of arrays in Qt.
Here is the code:
#include <QCoreApplication>
#include <iostream>
using namespace std;
int const sizeArray = 519199;
int main()
{
string arr[sizeArray];
for(int i = 0; i < sizeArray; i++)
{
arr[i] = i;
}
arr[499999] = "Test";
cout << arr[499999] << endl;
}
When sizeArray is 519999, the program runs quickly and displays "Test". But when sizeArray is 519200 or more, the program takes longer to run (approx 5s) then finishes without displaying "Test".
Is this a memory limit by the OS or by Qt?
When you write:
string arr[sizeArray];
You're creating an array of std::string type with size sizeArray on the stack. Don't create such big arrays on the stack, as you're going to fill it very quickly; and, you won't be able to do much in your program, as you keep all your local variables on the stack. Use dynamic arrays, such as std::vector or QVector instead.
Here's an example of std::vector:
std::vector<std::string> arr(sizeArray);
Also, don't use C-style arrays. If you want a stack-array that you know the size of, and that it won't be very large (i.e. it shouldn't exhaust the stack), use std::array instead, like so:
const int size_of_the_array = 10;
std::array<std::string, size_of_the_array> arr;
You're probably just getting a stack overflow at string arr[sizeArray];
The array is too big to fit in your program's stack address space.
If you allocate the array on the heap, then it should be fine, assuming your machine has enough memory.
string *arr = new string[sizeArray];
But remember that, once usage of arr is done, it will be required you to delete[] the array as below:
delete[] arr;
As previous answer, you can use vectors too, instead of using large array on Stack. To get better clarity you can check here
Anything other than automatic storage for the data of the array will work fine, though - and that's what you should use instead:
#include <QtCore>
#include <algorithm>
#include <array>
#include <memory>
static constexpr int N = 1000000;
static constexpr size_t pageSize = 4096;
template <typename R> void fill(R &range) {
std::generate(range.begin(), range.end(), [i = 0]() mutable {
return QString::number(i++);
});
qDebug() << *std::prev(std::cend(range));
}
int main() {
static QVector<QString> array1(N);
QVector<QString> array2(N);
QVarLengthArray<QString> array3(N);
auto array4 = std::make_unique<std::array<QString, N>>();//(new std::array<QString, N>);
static_assert(sizeof(array1) < pageSize);
static_assert(sizeof(array2) < pageSize);
static_assert(sizeof(array3) < pageSize);
static_assert(sizeof(array4) < pageSize);
fill(array1);
fill(array2);
fill(array3);
fill(*array4);
}
did you mean that it’s ok when the size is 519199 and not 519999?
anyway to check if it’s limit of the stack try to do it with new.
string *arr = new string[sizeArray]

Passing and modifying array of vectors through functions in c++

(I'm from C background and new in C++ and its STLs)
I'm writing a C++ array of vectors that will be passed (as a reference of an array of vectors) through a function and will be processed in it.
In this case [in C] I would have passed a pointer to my custom data type (call by value under the hood.)
My code that's giving errors in compile time while trying to do so:
#include <cstdio>
#include <vector>
using namespace std;
/*
the problem is I can't get the syntax. vector<type> &var is
a reference to a single dimension array of vectors.
*/
void pass_arrayOf_vect(vector<int> &array, int lmt);
int main() {
int lmt = 10;
vector<int> lst[lmt];
pass_arrayOf_vect(lst, lmt);
return 0;
}
/*
and the traditional ambiguity of whether using "." or "->" for
accessing or modifying indexes and their members.
*/
void pass_arrayOf_vect(vector<int> &lst, int lmt) {
for (int i = 0; i < lmt; i++) {
lst[i].push_back(i*i);
}
for (int i = 0; i < lmt; i++) {
printf("array[%d]: ", i);
for (int j = 0; j < lst[i].size(); j++) {
printf("%d ",lst[i][j]);
}
printf("\n");
}
printf("\n");
return;
}
In the main function the lst variable is an array of vectors. When you pass this to the pass_arrayOf_vect function you pass a pointer to the first element.
I.e. when you do
pass_arrayOf_vect(lst, lmt);
it's actually the same as doing
pass_arrayOf_vect(&lst[0], lmt);
So the function you call needs to accept a pointer to a vector as its first argument (not a reference):
void pass_arrayOf_vect(vector<int> *array, int lmt);
// ^
// Note use of asterisk instead of ampersand
An even better solution would be to use an std::array of vectors instead. Or if you're on an older compiler without support for std::array, or need the amount to be run-time configurable (in which case you can't use plain C-style arrays anyway), use a vector of vectors.

Filling array of pointers by function c++

Hello I have made class gabka and a function f1 to which I would like to pass an array of pointers to fill this array with gabka objects but I get weird error. How to correct it?
error:
cannot convert from gabka to int
the code :
#include <iostream>
using namespace std;
const int n = 4;
class gabka {
public:
float woda;
gabka(){
woda = 0;
}
void f1(gabka t[n]){
for(int i = 0; i < n; i++){
t[i] = new gabka();
}
}
};
int main() {
gabka** t = new gabka*[n];
return 0;
};
Your f1 function takes an array of gabka objects, and you are trying to assign a gabka* to each one of them. You need to decide what you want to pass to f1. For example,
void f1(gabka t[n]){
for(int i = 0; i < n; i++){
t[i] = gabka(); // assign default constructed gabkas
}
}
or
void f1(gabka* t[n]){
for(int i = 0; i < n; i++){
t[i] = new gabka();
}
}
In the latter case, bear in mind you have to call delete on all the elements of t.
It isn't clear what you are intending to do with your code, but, as a general rule, in C++ you should avoid raw pointers and manual dynamic allocation. Prefer standard library containers over dynamically allocates arrays or arrays of dynamically allocated objects.
t[i] = new gabka();
t is an array of gabka, not an array of gabka*.
Either change the declaration of t to be an array of gabka*, or fill it with gabka instances.

Accessing an entire row of a multidimensional array in C++

How would one access an entire row of a multidimensional array?
For example:
int logic[4][9] = {
{0,1,8,8,8,8,8,1,1},
{1,0,1,1,8,8,8,1,1},
{8,1,0,1,8,8,8,8,1},
{8,1,1,0,1,1,8,8,1}
};
// I want everything in row 2. So I try...
int temp[9] = logic[2];
My attempt throws the error:
array initialization needs curly braces
I know I can retrieve the row using a FOR loop, however I'm curious if there was a more obvious solution.
That's not how arrays/pointers work in C++.
That array is stored somewhere in memory. In order to reference the same data, you'll want a pointer that points to the the beginning of the array:
int* temp = logic[2];
Or if you need a copy of that array, you'll have to allocate more space.
Statically:
int temp[9];
for (int i = 0; i < 9; i++) {
temp[i] = logic[2][i];
}
Dynamically:
// allocate
int* temp = new int(9);
for (int i = 0; i < 9; i++) {
temp[i] = logic[2][i];
}
// when you're done with it, deallocate
delete [] temp;
Or since you're using C++, if you want to not worry about all this memory stuff and pointers, then you should use std::vector<int> for dynamically sized arrays and std::array<int> for statically sized arrays.
#include <array>
using namespace std;
array<array<int, 9>, 4> logic = {
{0,1,8,8,8,8,8,1,1},
{1,0,1,1,8,8,8,1,1},
{8,1,0,1,8,8,8,8,1},
{8,1,1,0,1,1,8,8,1}
}};
array<int, 9> temp = logic[2];
As well as decaying the array to a pointer, you can also bind it to a reference:
int (&temp)[9] = logic[2];
One advantage of this is it will allow you to use it C++11 range-based for loops:
for (auto t : temp) {
// stuff
}
A direct assignment won't work. C++ does not allow that. At best you'll be able to assign them to point to the same data - int *temp = logic[2]. You'll need a for loop or something like the below.
I believe this would work:
int temp[9];
memcpy(temp, logic[2], sizeof(temp));
But I'd generally suggest using std::vector or std::array instead.

Converting a vector to an array - Is there a 'standard' way to do this?

I know you can just do: &theVector[0], but is this standard? Is this behavior always guaranteed?
If not, is there a better, less 'hackish' way to do this?
Yes, that behavior is guaranteed. Although I can't quote it, the standard guarantees that vector elements are stored consecutively in memory to allow this.
There is one exception though:
It will not work for vector<bool> because of a template specialization.
http://en.wikipedia.org/wiki/Sequence_container_%28C%2B%2B%29#Specialization_for_bool
This specialization attempts to save memory by packing bools together in a bit-field. However, it breaks some semantics and as such, &theVector[0] on a vector<bool> will not work.
In any case, vector<bool> is widely considered to be a mistake so the alternative is to use std::deque<bool> instead.
C++11 provides the data() method on std::vector which returns a T*. This allows you to do:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> vector = {1,2,3,4,5};
int* array = vector.data();
std::cout << array[4] << std::endl; //Prints '5'
}
However, doing this (or any of the methods mentioned above) can be dangerous as the pointer could become invalid if the vector is resized. This can be shown with:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> vector = {1,2,3,4,5};
int* array = vector.data();
vector.resize(100); //This will reserve more memory and move the internal array
//This _may_ end up taking the place of the old array
std::vector<int> other = {6,7,8,9,10};
std::cout << array[4] << std::endl; //_May_ now print '10'
}
This could could crash or do just about anything so be careful using this.
We can do this using data() method. C++11 provides this method.
It returns a pointer to the first element in the vector. vector Even if it is empty, we can call this function itself without problems
vector<int>v;
int *arr = v.data();
A less 'hackish' way? Well you could simply copy :
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> vect0r;
int array[100];
//Fill vector
for(int i = 0; i < 10 ; i++) vect0r.push_back( i ) ;
//Copy vector to array[ ]
for( i = 0; i < vect0r.size(); i++) array[i] = vect0r[i];
//Dispay array[ ]
for( i = 0; i < vect0r.size(); i++) cout<< array[i] <<" \n";
cout<<" \n";
return 0;
}
More here : How to convert vector to array in C++