I want to pass 2-dimensional arrays with different sizes to my class and store the arrays as private member variables.
When I try to declare the array in the constructor I get an error.
How should I declare a private variable from constructor?
If it is not possible, what else can I do to make my class flexible for different array sizes?
Here is the header file:
#ifndef NUMCPP_H
#define NUMCPP_H
class numcpp
{
public:
numcpp(int *Arr,int *Shape,int Dims);
private:
int *shape;
int dims;
};
#endif
Here is the source file:
#include <iostream>
#include "numcpp.h"
using namespace std;
numcpp::numcpp(int *Arr,int *Shape,int Dims) // *arr points to input array's first element
{
shape = Shape;
dims = Dims;
int i = shape[0];
int j = shape[1];
int numcpp::array[i][j]; // error happens in this line
//assigning input array to our variable
for (int x = 0; x < i; x++)
{
for (int y = 0; y < j; y++)
{
array[x][y] = *(arr + (x * i) + y);
};
};
};
Classes must have a compile time fixed size, so a true flexible array member isn't possible. The best you could do is either:
Templating the class on the array dimensions (compile time chosen fixed size)
Using a dynamically resizable type like std::vector<std::vector<int>> to get something functionally similar (runtime dynamically chosen size); the class itself remains fixed size, with the vector storing the dynamically allocated arrays on the free store (heap).
One implementation approach would look something like this (adding a declaration of std::vector<std::vector<int>> array; in the private section of the class declaration):
// Use initializers to initialize directly instead of default initializing, then replacing
numcpp::numcpp(int *arr,int *Shape,int Dims) : shape(Shape), dims(Dims), array(shape[0], std::vector<int>(shape[1]))
{
int i = shape[0];
int j = shape[1];
for (int c = 0; c < i * j; ++c) {
array[c / j][c % j] = arr[c];
}
};
Related
I have a trouble with usage of private members of the class! I try to read and remember data into them in main.cpp file. I don't need to create any other values to remember read data. How to fix this problem and use them? I use <fstream> library to read data from file and remove them into ofstream file for output. I use .h files and .cpp files and main.cpp file.
Here is code in matrix.h file:
class Matrix
{
private:
int R; // amount of rows
int C; // amount of columns
double **mat; // pointer to two-dimensional array
public:
Matrix(); // default constructor
Matrix(Matrix &&) // move constructor
Matrix(int, int); // constructor with two parameters
double &ReturnReferenceToElement(int, int); // method to return reference to element of array
}
This is matrix.cpp file:
#include <iostream>
#include "matrix.h"
Matrix::Matrix()
{
R = 3;
C = 3;
mat = new double *[R];
for(int i = 0; i < R; i++)
{
mat[i] = new double [C];
}
}
Matrix::Matrix(Matrix &&M)
{
R = M.R;
C = M.C;
for(int i = 0; i < R; i++)
{
for(int j = 0; j < C; j++)
{
mat[i][j] = M.mat[i][j];
}
}
}
main.cpp:
#include <iostream>
#include <fstream>
#include "matrix.h"
using namespace std;
int main()
{
Matrix m;
ifstream in("in.txt");
ofstream out("out.txt");
in >> R >> C; // here I try to read data from file into private member
for(int k = 0; k < R; k++)
{
for(int s = 0; s < R; s++)
{
in >> mat[k][s]; // here I try to read into the private member
}
}
out << SumOfElements(**mat, R, C);
out << Averaged_Matrix(**mat, R, C);
return 0;
}
Functions SumOfElements() and Averaged_Matrix() are written in another file which is connected, and they work correctly.
Is it possible to use private members without setters and getters?
You're not allowed to access private fields from outside the containing class. But it looks like you have a constructor that takes R and C -- so read those fields then construct a Matrix object, passing R and C as arguments.
The idea of private methods is that you very specifically aren't supposed to touch them. So you can either add getters and setters, or you can reframe how you're trying to do what you're trying to do.
int r, c;
cin >> r >> c;
Matrix m(r, c);
If you ever feel the need to access private members of a class, then there's something terribly wrong. Either with the classes design, or in the way you want to interact with it.
In your particular case, the class design itself is ill conceived. In particular the problem attempted to be masked by declaring certain members private is, that altering them after construction will corrupt the classes behavior.
Your approach to this makes this is a XY problem: You think that you have to somehow deal with the access specifier, when in fact, the non-constness of members of the class that must not be altered is the cause of your troubles.
BTW: double **mat; does not make a 2D array. It makes an (1D) array of pointers to (1D) arrays of doubles. The two level indirection upon access will kill performance, not to speak of the high likelyhod that rows/columns of the matrix won't be contiguous in memory and thus will perform poorly due to cache misses and it being hard to prefetch.
A much better design for you class would look like this
#include <cstddef>
#include <cmath>
class Matrix
{
public:
typedef unsigned short dim_t;
dim_t const R; // amount of rows
dim_t const C; // amount of columns
double *const mat; // pointer to two-dimensional array
// NO DEFAULT CONSTRUCTOR!
// copy constructor
Matrix(Matrix const &m)
: R(m.R), C(m.R)
, mat(new double[(size_t)R * (size_t)C])
{
auto const N = (size_t)R * (size_t)C;
for(size_t i = 0; i < N; ++i){ mat[i] = m.mat[i]; }
}
// constructor with two parameters
Matrix(dim_t const r_, dim_t const c_)
: R(r_), C(c_)
, mat(new double[(size_t)R * (size_t)C])
{
auto const N = (size_t)R * (size_t)C;
for(size_t i = 0; i < N; ++i){ mat[i] = NAN; }
}
~Matrix(){ delete[] mat; }
// methods to return reference to element of
// !!! THOSE DO NOT PERFORM BOUNDS CHECKS!
double &operator()(dim_t const r, dim_t const c)
{ return mat[(size_t)R*(size_t)c + (size_t)r]; }
double const &operator()(dim_t const r, dim_t const c) const
{ return mat[(size_t)R*(size_t)c + (size_t)r]; }
};
Why is this better? First and foremost, by being declared const members of the struct, the need to "hide" them from the outside, that is protecting them from unintended alteration is gone; if one really want to be so hard pressed to alter those elements it can be done by forcing the compiler into undefined behavior, but the same methods would also allow to discard the access specifiers.
Thus where you feel the need to directly access elements of Matrix::mat you can do so, in relative safety. The compiler will forbid you to alter the
Now you might wonder why I declared a type for the dimensions that is unsigned short. The reason for this is, that on most relevant architectures and platforms out there (except 8 and 16 bit microcontrollers), the result of multiplication of the short will always fit into a size_t, so this prevents running into an integer overflow bug on allocation of the 2D array.
You can then use that like this:
#include <iostream>
#include <fstream>
#include "matrix.h"
int main()
{
std::ifstream in("in.txt");
Matrix::dim_t R, C;
in >> R >> C;
Matrix m(R,C);
for( Matrix::dim_t k = 0; k < m.R; k++ )
for( Matrix::dim_t s = 0; s < m.C; s++ ){
in >> m(k, s);
}
std::ofstream out("out.txt");
out << SumOfElements(m.mat, m.R, m.C);
out << Averaged_Matrix(m.mat, m.R, m.C);
return 0;
}
Suppose that I have a class like this one:
class SpinSystem{
private:
int L;
int L2;
const int k=1, J=1;
const int teq, tcorr;
const double TC=2/log(1+sqrt(2.0));//TC=2.269;
double Temp;
int Nmuestras;
int s[L][L]; int E,M;
int Cluster[L2][2]; int write;
public:
void set_values(int, double, int);
};
void SpinSystem::set_values(int length, double temperature, int nsamples){
L = length;
Temp = temperature;
Nmuestras = nsamples;
L2 = length*length;
teq = (int)(10*pow(length/8.0,0.58));
tcorr = (int)(1*pow(length/8.0,0.58));
}
The private variables L2, teq, tcorr depend on the value of L. This is why I set their values with the method set_values. However, I have to define some arrays, such as s[L][L] and Cluster[L2][2], whose sizes clearly depend on L. How can I achieve this? Thanks in advance.
You should handle all this in a constructor; init functions have all kinds of associated problems. And you should ensure that variables are listed in dependency order (i.e. if one variable depends on another, the latter must be declared first). Also, fixed constants can simply be made static as they are always the same. You don't need to keep variables that are trivially derived from others like L2. Initialize things inline when you can.
class SpinSystem{
private:
static constexpr int k=1;
static constexpr int J=1;
static constexpr double TC=2/log(1+sqrt(2.0));//TC=2.269;
int teq = (int)(10*pow(length/8.0,0.58));
int tcorr = (int)(1*pow(length/8.0,0.58));
int L;
double Temp;
int Nmuestras;
std::vector<int> s;
int E;
int M;
std::vector<int> Cluster;
int write;
public:
void SpinSystem(int length, double temp, int nsamples)
: L(length)
, Temp(temp)
, NMmuestras(nsamples)
{
s.resize(L*L);
Cluster.resize(L*L*2);
}
};
Here I create one dimensional arrays of the same total size. I strongly recommend you just do that and use a simple function to convert the index as you need to. But if you don't like that you can always have nested vectors.
Make sure in your real code to initialize E, M, and Write... preferably inline or in the initializer list.
From your code, you need to allocate a dynamic 2D array.
This is actually an array of pointers to arrays.
int _tmain(int argc, _TCHAR* argv[])
{
int L = 10; // get from command line
int ** s = new int*[L];
for (int i = 0; i < L; i++)
s[i] = new int[L];
// DO SOMETHING
// free memory
for (int i = 0; i < L; i++)
delete[] s[i];
delete[] s;
return 0;
};
I'm a high school student learning programming and I have a problem that I can't figure out how to solve.
I have an integer "x", and I want a matrix "mat" to have the size of "x":
int mat[x][x];
But that works only in main() where I've read x;
For example if x == 5, the equivalent would be
int mat[5][5];
#include <iostream>
using namespace std;
int x;
int mat[x][x];
void f(int mat2[x][x])
{
}
int main()
{
cin >> x;
int m[x][x];
f(m);
}
I've wrote this short program to show where it works and it doesn't work.
error: array bound is not an integer constant before ']' token
I've the error at the global declaration, at the declaration in function void f. It only compiles without errors in main();
What can I do to create a matrix with the size of x outside of the main function?
Variable length arrays aren't spported in standard c++. Besides you don't want the global definition.
What you can use portably in that case is std::vector:
void f(std::vector<std::vector<int>>& mat)
{
}
int main()
{
cin >> x;
std::vector<std::vector<int>> m(x,std::vector<int>(x));
f(m);
}
If you pass that vector around to functions or being allocated within functions, the size information will be kept at any time.
What can I do to create a matrix with the size of x outside of the main function?
Something like this:
std::vector<std::vector<int>> foo() {
cin >> x;
std::vector<std::vector<int>> m(x,std::vector<int>(x));
return m;
}
int main()
{
std::vector<std::vector<int>> mat = foo();
}
Handling of multi-dimension arrays in C++ is not easy. The best way to go is often to map a multi-dimensionnal indexing with a linear memory chunk.
For instance, for a 2 by 2 matrix, one can create an array of 2*2=4 elements and map it this way:
+-----------+-----------+-----------+-----------+
| map[0][0] | map[0][1] | map[1][0] | map[1][1] |
+-----------+-----------+-----------+-----------+
This seems overly complicated at first glance, but it simplifies greatly the memory allocation.
For an arbitrary sized matrix of width by height, map[i][j] is at index i*height + j. This can be translated in C++, encapsulated in a template class Matrix:
#include <array>
template <typename T, size_t WIDTH, size_t HEIGHT>
class Matrix {
std::array<T, WIDTH*HEIGHT> data;
public:
T& operator()(size_t i, size_t j) {
return data[i*HEIGHT + j];
}
const T& operator()(size_t i, size_t j) const {
return data[i*HEIGHT + j];
}
};
This has the disadvantage that the Matrix' dimensions must be known at compile time (and can be mitigated, see note (ii) at end of answer). But it makes its use so easy:
void fill(Matrix<int, 2, 2>& m) {
m(0,0) = 0;
m(0,1) = 1;
m(1,0) = 2;
m(1,1) = 3;
}
int main() {
Matrix<int, 2, 2> m;
fill(m);
std::cout << m(1,0) << "\n";
}
Note (i): Elements are indexed by (line, column) rather than [line][column] because we can't create an operator[] accepting multiple values.
Live on coliru
Note (ii): This basic idea can be enriched (demo) to handle resizable matrixes, with use of a std::vector instead of std::array and a proxy to std::vector::resize().
Variable-length array is supported by some compiler as an extension. The manual of the compiler provides more information.Gnu VLR
The storage duration of a variable-length array(if supported) generally can't be static, which is why you get the error message (global variables have static storage duration).
Unrelated: The major array bound of the parameter mat2 isn't necessary, i.e. void f(int mat2[x][x]) is equivalent to void f(int mat2[][x]).
C++ has no provision for dynamic 2D matrix but provides all you need to create complex classes. A (static) 2D array is a contiguously allocated array of height arrays of width elements. Just mimic that and:
allocate a linear array of width * height
provide an operator[](int) that returns a pointer to the first element of ith row
do necessary housekeeping in destructor and in a copy (and move if C++11 or above) constructor.
Example of code:
template <typename T>
class Matrix {
T *data;
int width;
int height;
public:
// direct ctor
Matrix(int h, int w): width(w), height(h) {
data = new T[w * h];
}
//copy ctor
Matrix(const Matrix& src): width(src.width), height(src.height) {
data = new T[width * height]; // allocate and copy data array
for (int i=0; i<width * height; i++) data[i] = src.data[i];
}
// move ctor
Matrix(Matrix&& src): width(src.width), height(src.height) {
data = src.data; // steal original array in a move
src.data = NULL; // ensure no deletion will occur at src destruction
}
~Matrix() {
delete data;
data = NULL;
}
// explicitely delete assignement operators
Matrix& operator = (const Matrix&) = delete;
Matrix& operator = (Matrix&&) = delete;
T* operator[](int i) {
//optionaly test 0 <= i < width
return &data[i * width];
}
};
int main()
{
int w;
std::cin >> x;
Matrix<int> m(x, x);
// you can then use m[i][j] as you would for a static 2D array
...
}
This class does not support any resizing by design. If you need that, you really should use a vector<vector<T> >. The downside is that it has no default ctor either, because the dimension must be given at definition time (even if we could easily imagine a 2 phases initialization...).
You can dynamic allocate memory to use, in the c/c++, it does not support dynamic size of static memory allocation, so, you just modify your code like this.
int x;
cin >>x;
int** mat = new int[x][x];
Here is the deal. We have 2 different classes Class F and Class O
class F {
private:
int x;
int y;
public:
int getXf(){ return x; }
int getYf(){ return y; }
f(int ,int);
};
class O {
private:
int n;
int k;
int x;
int y;
char type;
int id;
int t;
public:
O(int ,int ,int ,int ,int);
int getX(){ return x; }
int getY(){ return y; }
};
And we have a third class P, where we initialize the values. In the class we are creating the two arrays of objects.
class Prog {
public:
int count;
int fcount;
O *o[]; //here we are declaring the arrays of objects
F *f[];
public :
//void init(); Here is the function where we initializing the values
};
Now the 2 for statements where we are creating the objects.
for(int i=0;i<10;i++){
randx = rand() % 10;
randy = rand() % 20;
o[i] = new O(100,50,i,randx,randy);
}
for(int i=0;i<3;i++){
randx = rand() % 10;
randy = rand() % 10;
f[i] = new F(randx, randy);
}
When we are printing all of the objects are here but the first 3 of the first class are replaced by the objects of the seconds. Exactly the 100 and 50 (1st for) from randx and randy (2nd for) respectively.
O *o[];
This declares an array of unknown size, which is an incomplete type. C++ doesn't allow that to be used as a class member, although some compilers will allow it as an extension, interpreting it as an array of zero size. In either case, it's not what you want.
If you know the array bound at compile time, then you should specify it:
O *o[10];
otherwise, you'll need to dynamically allocate an array at run time:
std::vector<O*> o;
for(int i=0;i<10;i++){
randx = rand() % 10;
randy = rand() % 20;
o.push_back(new O(100,50,i,randx,randy));
}
I would also suggest storing objects, or possibly smart pointers, rather than raw pointers in the array. If you really do want raw pointers for some reason, then remember to delete the objects once you've finished with them since that won't happen automatically, and don't forget the Rule of Three.
You are declaring arrays, but you never allocate memory for them. What you are seeing is just how your code is walking all over the stack.
Something more appropriate:
struct X {}; struct Y {};
class P {
public:
P() : xs(new X*[10]), ys(new Y*[10]) { init(); }
~P() {
// delete all objects
for(std::size_t i = 0; i < 10; ++i)
delete xs[i];
for(std::size_t i = 0; i < 10; ++i)
delete ys[i];
delete[] xs;
delete[] ys;
}
private:
void init() {
// initialize
for(std::size_t i = 0; i < 10; ++i)
xs[i] = new X();
for(std::size_t i = 0; i < 10; ++i)
ys[i] = new Y();
}
// prevent assignment and copy
P& operator=(const P& other);
P(const P&);
X** xs;
Y** ys;
};
Of course, all this magic becomes unnecessary if you just use
std::vector to store your data.
The problem is due to the way you declare your arrays:
O *o[/*No size here*/];
F *f[/*No size here*/];
Since you do not state the size of the arrays, this is equivalent to
O **o;
F **f;
Hence, you are declaring two members of types "pointer to pointer to O" and "pointer to pointer to F" respectively, but these are uninitialized and you have not allocated any memory for them to point to. That is, you actually don't have any arrays, just pointers which could be used to refer to the type of array you want.
If you know at compile time what size you want to use, you should specify that size in the declaration, which will give you a properly allocated array of that size. Otherwise, consider using an std::vector.
In C++ how initialize all values of a member array for a class?
#define MAX_MATRIX 20
Class Matrix {
public:
Matrix(); //constructor
protected:
int n[MAX_MATRIX]; // note cannot do = { 0} or w/e here
};
Matrix::Matrix()
{
// how to set all n to -1?
}
You can use std::fill:
std::fill(begin(n), end(n), -1);
(These begin and end functions can be found in namespace std in C++11, or you can easily implement them yourself in C++03)
This was a glaring shortcoming of C++03. In C++11 this has been fixed, and you can now initialize everything, including arrays:
class Matrix
{
public:
Matrix() : n { } { }
protected:
static const unsigned int MAX_MATRIX = 20;
int n[MAX_MATRIX];
};
(The nasty preprocessor macro is also not needed in C++.)
In C++03, you simply cannot initialize an array member, but you can set it to something meaningful in the constructor body, e.g. via std::fill(n, n + MAX_MATRIX, 0);.
(Of course it would be a lot nicer to say std::array<int, MAX_MATRIX> n;.)
There's a type for this:
class Matrix {
public:
Matrix() : n() { n.fill(-1); }
protected:
std::array<int, 20> n;
};
for (unsigned i = 0; i < MAX_MATRIX; ++i) n[i] = -1;
#include <cstring>
...
Matrix::Matrix()
{
static bool init=false;
static int n_init[MAX_MATRIX];
if (!init){
for(int i=0; i<MAX_MATRIX; i++){
n_init[i] = -1;
}
init = true;
}
memcpy(n,n_init,MAX_MATRIX*sizeof(int));
}
The array n_init is initialized exactly once and stored in memory, then all subsequent constructions are a quick memory copy with no loops. You should not see much decrease in speed if you increase the size of MAX_MATRIX as you would when looping through the index, particularly if you are calling Matrix::Matrix() many times.