I need to parse output variables only once up front, rather than at each time step, so I originally produced a pointer array of output variable pointers (float ***outVars). I could run through the list of pointers after each time interval, and since outVars pointed to the original data, they would always provide the current state of the model.
I'm changing code from matrices of naked pointers to matrices of vectors. I haven't been able to return anything but copies of vectors, rather than references to the original vectors. I don't want to modify the vectors, I just need direct read access.
I can't believe I haven't found my answer online yet. Most that I've found online has simply said use std::vector<float> & to return by reference, but clearly that isn't working.
I saw one note that assigning a reference to a non-reference value (I assume they meant variable) will make it copy, so I tried fvec2D &outVar2D; (see the header file below).
I've tried with and without const, no difference.
I've tried returning vector.data(), but assigning it to a new vector was also copying. Maintaining pointers to .data() memory blocks seems be a very bad idea, if I need to resize the original vector.
I've tried wrapping the vector in std::shared_ptr, but found I'd need to wrap each dimension vector in a shared_ptr, which got overly cumbersome real fast.
I saw one suggestion to return vector::iterators. I haven't managed to get that to work yet. Maybe having 2D data is getting in the way of that. I'm still trying to get that to run without crashing when I examine the iterator.
I don't know if using a 1D array would solve this, but calculating every index reference for millions of calls seems suboptimal. I considered using std::array too but vectors seemed the simplest conversion. Perhaps I should rethink that.
If anyone has any suggestions for how to do this, I'd very much appreciate it.
The following code works in Qt, though I've replaced calls to qDebug with calls to cout.
file chem.cpp
#include <memory>
#include <vector>
class chem
{
public:
typedef std::vector<float> fvec1D;
typedef std::vector<std::vector<float> > fvec2D;
typedef std::vector<std::vector<std::vector<float> > > fvec3D;
chem(int xstep, int zstep) : concentration(xstep, fvec1D(zstep, 1.5)) {}
void changeConc( int x, int z, float num) {concentration[x][z] = num;}
// tried this with and without const
const fvec2D &getConc() const { return concentration; }
const fvec1D &getConc(int x) const {return concentration[x]; }
private:
fvec2D concentration;
}
file model.h
#include <memory>
#include <vector>
#include <iostream>
#include "chem.cpp"
class model
{
public:
typedef std::vector<float> fvec1D;
typedef std::vector<std::vector<float> > fvec2D;
typedef std::vector<std::vector<std::vector<float> > > fvec3D;
model();
void run();
void plot();
private:
int numChems = 1; // normally determined at runtime
int numXSteps = 3; // normally determined at runtime
int numZSteps = 25; // normally determined at runtime
fvec2D &outVar2D; // tried these with and without &
fvec1D &outVar1D;
std::vector<std::unique_ptr<chem> > chemList;
}
file model.cpp
#include "model.h"
model::model()
{
chemList.resize(numChems);
chemList[0].reset(new chem(numXSteps, numZSteps) );
outVar2D = chemList[0]->getConc(); // or
outVar1D = chemList[0]->getConc(1);
}
void model::plot()
{
for (int z=0; z<numZSteps; ++z) {
std::cout << outVar1D[z];
std::cout << outVar2D[1][z];
}
}
void model::run()
{
std::cout << "initial plot().";
plot(); // produces init concentration of 1.5 at each z
for (int z=0; z<numZSteps; ++z)
chemList[0]->changeConc(1, z, (float) z);
std::cout << "final plot().";
plot(); // STILL produces init conc of 1.5 at each z
}
Aucun commentaire:
Enregistrer un commentaire