I'm wondering how to get the maximum data locality and performance for the following problem without data copy.
I've a std::vector< MyClass* > where MyClass is something like
class MyClass
{
public:
MyClass(int n,double px,double py,double pz)
{
someField=n;
x=px;
y=py;
z=pz;
anotherField=100;
anotherUnusefulField=-10.0;
}
int someField;
int anotherField;
double x;
double y;
double z;
double anotherUnusefulField;
};
std::vector<MyClass*> myClassVector;
// add some values and set x,y,z
for (std::vector<MyClass*>::iterator iter = myClassVector.begin(); iter!=myClassVector.end();++iter)
{
MyClass *tmp = *iter;
tmp->x+=1.0;
tmp->y+=2.0;
tmp->z+=3.0;
}
I'm iterating frequently on these data and I also would like to enforce data locality. The data contained in the pointer to MyClass should be sent to a OpenGL vertex array, where the vertices are ONLY determined by x,y,z variables. As you may imagine is difficult to correctly set the strides, so I'm here to ask if there are other (portable) solution to this problem.
(p.s. I've already read the post VBOs with std::vector but my case is basically different because I have pointers and I also have other variables inside the class.)
I have pointers
Those pointers are useless to OpenGL, as they're in client address space. Also OpenGL doesn't dereference second level pointers.
and I also have other variables inside the class.
Well, then don't do this. If you passed those class instances to OpenGL you'd copy a lot of useless data. I recommend you just store a index into a tightly packed std::vector or array in your class members, and a reference to the vector/array itself. You can use getter/setter/referencer member functions to abstract away the access to the vector, i.e.
class …
{
// …
std::vector<v_t> *v;
size_t index_v;
x_t getX() const { return (*v)[index_v]; }
x_t setX(x_t x) { return (*v)[index_v] = x;}
x_t &x() { return (*v)[index_v]; }
};
Related
I am experimenting with a simple vertex class.
class Vertex
{
public:
std::vector<float> coords;
//other functionality here - largely irrelevant
};
And lets say we create a Vertex object as below:
Vertex v0(1.f, 5.f, 7.f);
I am wondering if there is anyway to assign a name to each element of a vector?
Let's say that each std::vector will only ever have a size of 3. I know I can access an element or index of the vector in a way such as v0.coords[0] through to v0.coords[2];
However, I am wondering if there is a way in which I could assign a name to each element of the vector, ie:
v0.coords.x == v0.coords[0];
v0.coords.y == v0.coords[1];
v0.coords.z == v0.coords[2];
So that if I was to access the vector, I could access via a name rather than an index.
Is such a thing possible? If so, how do I go about creating such aliasing?
I am wondering if there is anyway to assign a name to each element of a vector?
No, there is not. At least, not the way you want.
I suppose you could use macros, eg:
#define coords_x coords[0]
#define coords_y coords[1]
#define coords_x coords[2]
Now you can use v0.coords_x, v0.coords_y, and v0.coords_z as needed.
Or, you can use getter methods, eg:
class Vertex
{
public:
vector<float> coords;
//other functionality here - largely irrelevant
float& x(){ return coords[0]; }
float& y(){ return coords[1]; }
float& z(){ return coords[2]; }
};
Now you can use v0.x(), v0.y(), and v0.z() as needed.
But really, in this situation, there is just good no reason to use a vector at all. It is simply the wrong tool for the job. Use a struct instead, eg:
struct Coords
{
float x;
float y;
float z;
};
class Vertex
{
public:
Coords coords;
//other functionality here - largely irrelevant
};
Alternatively:
class Vertex
{
public:
struct
{
float x;
float y;
float z;
} coords;
//other functionality here - largely irrelevant
};
Now you can use v0.coords.x, v0.coords.y, and v0.coords.z as needed.
i trying to implement the following link http://in.mathworks.com/help/vision/examples/motion-based-multiple-object-tracking.html in opencv and c++.
I have created a class say ex:
class assign
{
vector <int> id;
vector <int> area;
vector<Point> centroid;
};
After this i have created an object
assign id;
Now i want to assign the centroid value and other values too. what i tried is
id.centroid (p);
where p is a "point" But i'm getting error for this. I don't know where i'm going wrong.
centroid is a private member of class assign. If you want to access it directly, you should make it public
class assign
{
public:
vector<Point> centroid;
//...
};
And if you want to add a Point into centroid, you should
id.centroid.push_back(p);
The main answer is already given by songyuanyao. What I want to add is a possible solution which allows you to use the member variables like you already tried it.
If you want to get and set the member centroid with id.centroid(p) you could go with the following class declaration:
class Assign
{
public:
vector<Point> centroid();
void centroid(vector<Point> c);
private:
vector<Point> m_centroid;
};
The definition might then look like this:
// getter
vector<Point> Assign::centroid() {
return m_centroid;
}
// setter
void Assign::centroid(vector<Point> c) {
m_centroid = c;
}
Now if you use id.centroid(p) to set the member the overloaded setter will be called and will set the variable. If you call p = id.centroid() (empty parameter list) the overloaded getter will be called and will return the current m_centroid.
To add to the previous answers; if you want to expand on your class this can be done for you during construction of your object.
class Assign {
private:
std::vector<int> m_vIds;
std::vector<int> m_vAreas;
std::vector<Vec2> m_vCentroids;
public:
Assign(); // Default Constructor Same As What You Have But Not Declared.
Assign( int* pIds, int* pAreas, int* pCentroids ); // Create By Using Pointers
// Create By Passing In Either Pre Filled Vectors Or Even An Empty
// Vectors To Be Filled Out Later. Passes By Reference. This Will
// Also Set The Variables That Are Passed In From The Caller.
Assign( std::vector<int>& vIds, std::vector<int>& vAreas, std::vector<Vec2>& vCentroids );
// Since You Are Using Vectors Within This Class It Is Also Good To
// Have A Destructor To Clear These Out Once The Object Is Done And
// Ready To Be Destroyed Or Removed From Memory
~Assign();
};
// The Destructor Would Look Like This
Assign::~Asign() {
if ( !m_vIds.empty() ) {
m_vIds.clear();
}
if ( !m_vAreas.empty() ) {
m_vAreas.clear();
}
if ( !m_vCentroids.empty() ) {
m_vCentroids.empty();
}
} // ~Assign
// NOTE: I used Vec2 instead of point due to my use of programming
// 2D & 3D Graphics Rendering Engines; Most Graphics APIs and Libraries
// along with Most Math Libraries Will Not Have A Point Class; Most Will
// Use Vec2 or Vec3 - Vector2 or Vector3 & Vector4 Since in terms of
// memory they are exactly the same thing. It is up to you to know which
// objects are points or locations, and which are vectors as in forces,
// velocities, accelerations, directions, normals etc. The only major
// difference between a discrete Point Class or Structure versus a Vector
// Class is that the Vector Class usually has operations defined with it
// to do vector mathematics such as addition, subtraction, multiplication by
// value, multiplication by vector, division by value, division by vector,
// cross & dot product, comparisons, testing if vector is 0, setting it to
// be a normal vector, returning the magnitude or length and a few others.
// The general point class or object is usually just data values or
// simply coordinates without operations.
I am making a battleships game for my coursework, and I have run into some problems with the get functions in one of the classes I am using. The basic idea of my game is to create a 2D 10X10 array, called grid, filled with null pointers to represent the board. I have created 2 classes, Board and Ship. The grid array is of type Ship, and I use an algorithm to fill the array with Ships randomly. I use the Board class to access the grid array and the hits array (which I use to track hits).
However I cannot figure out how the getShips function can return the grid array. The hits array is just booleans so that was easy enough, but I am not proficient enough at C++ to make the getShips function properly return the grid array, which is a Ship pointer type. I would greatly appreciate any help.
class Board
{
private:
Ship *grid[10][10];
bool hits[10][10];
public:
// get functions
Ship *getShips()
{
return grid;
}
bool getHits()
{
return hits;
}
};
I was also wondering if it would be possible to manipulate the array in other functions by calling the getShips function. Something like:
for (int x=0; x<10; x++)
{
for (int y=0; y<10; y++)
{
board.getShips()[x][y]=nullptr;
}
}
Ok. First I would modify the getShips and getHits functions. To have something like that :
Ship *getShips(int x, int y){ return grid[x+y*10]; }
bool getHits(int x, int y){return hits[x+y*10];}
That way you'll simplify your code and avoid some errors.
When you declare a multidimensional array like you do with
Ship *grid[10][10];
bool hits[10][10];
you're basically declaring pointers to pointers to pointers to ships.
I would try to use a minimum amount of pointers if you're writing in C++. Try to use the stl containers instead. They do automatic memory management for you which may save you some time down the road.
I suggest to change your interface to something like:
class Board
{
private:
Ship *grid[10][10];
bool hits[10][10];
public:
Ship* getShip(int x, int y) const { return grid[x][y]; }
Ship*& getShip(int x, int y) { return grid[x][y]; }
bool getHit(int x, int y) const { return hits[x][y]; }
bool& getHit(int x, int y) { return hits[x][y]; }
};
If you really want to return grid and hits, I recommend to use std::array<std::array<Ship*, 10>, 10> grid; (require C++11) instead of Ship *grid[10][10];.
if C++11 is not possible turn back to std::vector.
and then
private:
std::array<std::array<Ship*, 10>, 10> grid;
public:
const std::array<std::array<Ship*, 10>, 10>& getShips() const { return grid; }
std::array<std::array<Ship*, 10>, 10>& getShips() { return grid; }
Currently, it looks like getShips is returning the entire 10x10 array of Ship*-- you need to change what the getShips function is returning:
Ship*** getShips() { ...
However, I would recommend against mixing pointers and arrays. Pointers can be tricksy, and combining with arrays can get very difficult to debug. Instead, you could use all pointers: Ship ***grid; and initialize with new (I'll leave the initialization as an exercise, but here's a site that has an example: http://pleasemakeanote.blogspot.com/2010/07/2d-arrays-in-c-using-new.html).
In reality, it might be better for the Ship class to store the indices of where it exists, perhaps something like this:
class Ship
{
public:
<<member func>>
private:
int nspaces_;
int start_[2];
int end_[2];
}
where you store the beginning index and the final index where the ship is found. You'll need to handle the code to identify the spaces between, but that is trivial. This setup would allow you to replace Ship *grid[10][10] with a single array of Ships.
The getShips function would then become:
...
Ship ships_[<<number of ships>>];
Ship *getShips()
{
return ships_;
}
...
and would be used:
board.getShips()[x][y]
Or...you could add a getShip(int x, int y) method.
I just heard of that there is a kind of type like this,a point to Object member. Here is it
class Point{float x, y;};
float Point::*p2 = &Point::x;
but I haven't use before,and wonder some-body really use it.Do you have any experience of that?
This is useful if you want to apply the same treatment to members without duplicating the code.
vector<Point> points; // suppose it has many elements
vector<double> Project(const vector<Point> points, int Point::* coord)
{
vector<double> result;
for (auto& p: points)
result.push_back(p.*coord);
return result;
}
// usage:
vector<double> Xs = Project(points, &Point::x);
vector<double> Ys = Project(points, &Point::y);
There are many other usages as well, for instance fast delegates (link).
Those are pointers to class members and are used for example to implement various functor classes (e.g.: boost::function or std::function).
http://en.cppreference.com/w/cpp/utility/functional/mem_fn
or
http://www.cplusplus.com/reference/std/functional/mem_fun/
class Point {
public: //public variables (can be accessed by outsider)
float x, y;
private: //private variables if you have any
};
Now to create an object you would do Point p, and you can access the elements by doing p.x and p.y, just like you would with a struct object.
If you want to create a class pointer, do Point *p, now if you want to access x, y, then you would do p->a and p->b. If you have another object Point t, and you want assign address of t to p, then you can do p = &t.
I'm an intermittent programmer and seem to have forgotten a lot of basics recently.
I've created a class SimPars to hold several two-dimensional arrays; the one shown below is demPMFs. I'm going to pass a pointer to an instance of SimPars to other classes, and I want these classes to be able to read the arrays using SimPars accessor functions. Speed and memory are important.
I know life is often simpler with vectors, but in this case, I'd really like to stick to arrays.
How do I write the accessor functions for the arrays? If I'm interested in the nth array index, how would I access it using the returned pointer? (Should I write a separate accessor function for a particular index of the array?) What's below is certainly wrong.
// SimPars.h
#ifndef SIMPARS_H
#define SIMPARS_H
#include "Parameters.h" // includes array size information
class SimPars {
public:
SimPars( void );
~SimPars( void );
const double [][ INIT_NUM_AGE_CATS ] get_demPMFs() const;
private:
double demPMFs[ NUM_SOCIODEM_FILES ][ INIT_NUM_AGE_CATS ];
};
#endif
// SimPars.cpp
SimPars::SimPars() {
demPMFs[ NUM_SOCIODEM_FILES ][ INIT_NUM_AGE_CATS ];
// ...code snipped--demPMFs gets initialized...
}
//...destructor snipped
const double [][ INIT_NUM_AGE_CATS ] SimPars::get_demPMFs( void ) const {
return demPMFs;
}
I would greatly appreciate some kind of explanation with proposed solutions.
Basically, you have three options: return the entire array by reference, return the first row by pointer, or return the entire array by pointer. Here is the implementation:
typedef double array_row[INIT_NUM_AGE_CATS];
typedef array_row array_t[NUM_SOCIODEM_FILES];
array_t demPMFs;
const array_t& return_array_by_reference() const
{
return demPMFs;
}
const array_row* return_first_row_by_pointer() const
{
return demPMFs;
}
const array_t* return_array_by_pointer() const
{
return &demPMFs;
}
And here are the use cases:
SimPars foo;
double a = foo.return_array_by_reference()[0][0];
double b = foo.return_first_row_by_pointer()[0][0];
double c = (*foo.return_array_by_pointer())[0][0];
How would I return just the nth row of the array?
Again, you have three choices:
const array_row& return_nth_row_by_reference(size_t row) const
{
return demPMFs[row];
}
const double* return_first_element_of_nth_row_by_pointer(size_t row) const
{
return demPMFs[row];
}
const array_row* return_nth_row_by_pointer(size_t row) const
{
return demPMFs + row;
}
const double (* get_demPMFs() const)[INIT_NUM_AGE_CATS];
Or, use typedef (but that doesn't seems cleaner...).
class SimPars {
typedef const double (*ConstDemPMFType)[INIT_NUM_AGE_CATS];
double demPMFs[NUM_SOCIODEM_FILES][INIT_NUM_AGE_CATS];
public:
ConstDemPMFType get_demPMFs() const;
};
Note that you can't return an array (g++ refuses the compile). But an array of array can be decayed to a pointer to array, so the latter is returned.
Logically speaking there is this question with a data member. Should users be allowed to modify it or not. If you want to give another class full access to the member, you don't necessarily need getter/setter, especially if you are the only user. You can just make the member public.
If your class would be better off controlling how users access the member, then you could use a getter only to enforce read only access. The simplest way to do this if you don't want to get all confused about the 2-dimensional arrays is to just have an inline function fetching the element for the user class:
const double& getElem( int x, int y ) const { return demPMF[x][y] }
It makes sense to do bounds checking here, but considering that you insist on using arrays, and if your profiler proves that you can't afford it, this function would just allow access to your array.
If you want further elaboration, post a comment...