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;
};
Related
I have a struct that contains a const array, and would like to initialise it to specific values upon construction. Unfortunately, its contents depend on several parameters which are passed into the constructor as parameters, and require a function to compute the contents of the array.
What I'd ideally like to do looks something like this:
struct SomeType {
const unsigned int listOfValues[32];
unsigned int[32] processParameters(unsigned int parameter) {
unsigned int arrayValues[32];
for(int i = 0; i < 32; i++) {
arrayValues[i] = i * parameter;
}
return arrayValues;
}
SomeType(unsigned int parameter) : listOfValues(processParameters(parameter)) {
}
};
Of course there are several issues here (returning an array from a function is not possible, data type mismatches, etc). However, is there any way this is possible?
I've seen other similar questions suggest using a std::vector for this, but the heap allocation(s) this incurs is something my performance budget can't afford.
As Nathan suggested you should change the raw array with an std::array. This way you still have the benefit of stack allocation but now you can initialize from a copy.
using MyArray = std::array<unsigned int, 32>;
const MyArray listOfValues;
MyArray processParameters(unsigned int parameter) {
MyArray arrayValues;
for(int i = 0; i < 32; i++) {
arrayValues[i] = i * parameter;
}
return arrayValues;
}
I removed the const from the array data type since it's not necesary because your array is const already, also with const unsigned int you wouldn't be able to set the values of arrayValues at run time.
Does this serve your purpose? No heap allocations that I can see.
struct SomeType {
const unsigned int *listOfValues;
const unsigned int * processParameters(unsigned int parameter) {
for(int i = 0; i < 32; i++) {
_listOfValues[i] = i * parameter;
}
return _listOfValues;
}
SomeType(unsigned int parameter) :
listOfValues(processParameters(parameter))
{
}
private:
unsigned int _listOfValues[32];
};
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];
}
};
I need to convert a plain double C-array to a VectorXd*. I found Map class that seems to do the job but there's something I didn't understand.
class A {
private:
VectorXd *jpos_;
public:
int init( double *v, int len )
{
// Here I would like to assign v to jpos_ in an efficient way
// (something like a pointer assignment without allocation or vector iterations)
// Note that length of v is len
}
};
I tried the following but it doesn't work:
int A::init( double *v, int len )
{
jpos_ = &VectorXd::Map( v, len );
}
or
int A::init( double *v, int len )
{
jpos_ = &Map<VectorXd>( v, len );
}
What's wrong?
Thanks.
Emanuele
If you want to map an array by means of Eigen::Map, your member jpos_ should be of type Eigen::Map:
class A
{
private:
Eigen::Map<Eigen::VectorXd> jpos_;
public:
A(double* v, int len) : jpos_ {v, len} {}
};
If you need to keep the VectorXd, you need to copy the values to the vector. It is a bit strange to see VectorXd*. It's similar like std::vector<double>*. I would recommend not using VectorXd*.
class A
{
private:
Eigen::VectorXd jpos_;
public:
A(double* v, int len) : jpos_ {v}
{
for (int i=0; i<len; ++i)
jpos_(i) = v[i];
}
};
EDIT:
If you really need VectorXd*, you can allocate one with new (and don't forget to delete it).
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.
I've just tried:
class Test
{
public:
int iArray[][];
}
...is this not possible? Do I have to set a constant value?
like:
class Test
{
public:
const int iArray[5][4];
}
I want to define [x][y] later, just have the placements there. Else it wouldn't be "dynamic" and I don't want to use a vector because I want to be able to access the values by "X" and "Y".
I think better way to achieve this is to use pointers. You can do like this.
#include <cstdlib>
#include <iostream>
using namespace std;
class PointerTest {
private:
int** array;
int x, y;
public :
void setValue(int row, int col,int value);
int getValue(int row, int col);
PointerTest(int row, int col);
~PointerTest() {
for(int i=0;i<x;i++) {
delete array[y];
}
}
};
PointerTest::PointerTest(int row, int col) {
x=row, y=col;
for(int i=0;i<row;i++) {
*array=new int[col];
}
}
void PointerTest::setValue(int row, int col, int value) {
*(array[row])=value;
}
int PointerTest::getValue(int row, int col) {
return *(array[row]);
}
int main(int argc, char *argv[])
{
PointerTest* t=new PointerTest(4,5);
t->setValue(0,0,464);
cout<<"The value in array: "<<t->getValue(0,0)<<endl;
system("PAUSE");
return EXIT_SUCCESS;
}
What about
tempalte <int N1, int N2> class Test
{
public:
int iArray[N1][N2];
};
?
What about putting a std::vector in a vector?
std::vector< std::vector< const int > > iArray;
There aren't many reason to use "plain" arrays in C++.
If you want to decide int iArray[][]; size later then you can use vector< vector<int> > iArray;.
The other way is to use nested new[], which would be little complex.
No this is not possible. But you can have a pointer in your class like
int **ptr;
and then in the constructor or where ever allocate the memory for your array with
ptr = (int **)malloc( the size you want );
or with the "new[]"-operator in C++.
but if you are using C++ .. the best way is to use:
std::vector< std::vector< int >> array;
class Test
{
public:
Test()
{
iArray = new int*[5];
for(int i = 0; i < 5; i++)
iArray[i] = new int[4];
}
~Test()
{
for(int i = 0; i < 5; i++)
delete[] iArray[i];
delete[] iArray;
}
int** iArray;
};
Will allow you to allocate a 2d int array at runtime (in this example it is a 5x4), but in all honestly I would use vectors as pointed out by some other posters, you don't need to worry about freeing the memory afterwards like you do with the use of new.