I have the following class for points:
class MyPoint
{
public:
// Constructor
MyPoint(double, double, double);
// Destructor
virtual ~MyPoint(){};
protected:
private:
double x;
double y;
double z;
};
I would like to create a vector of myPoints to store some data:
vector <MyPoint> vectorOfPoints
for (int i = 0; i < 10 ; i++)
{
vectorOfPoints.push_back(MyPoint(1,2,3));
}
And I would like to create a class called myFaces to store the address of the points that make up a face.
e.g.,
Face A is built with vectorOfPoints[0], vectorOfPoints[2], vectorOfPoints[5] and vectorOfPoints[6].
How can I pass a vector with the addresses of the above entries to the class myFace?
class myFace
{
public:
// Constructor
myFace(int, vector<std::shared_ptr<Point> > );
// Destructor
virtual ~myFace(){};
protected:
private:
int nPointsInFace_;
vector<std::shared_ptr<Point> > refToPointsThatMakeUpThisFace_;
};
Would really appreciate the help!
Face A is built with vectorOfPoints[0], vectorOfPoints[2], vectorOfPoints[5] and vectorOfPoints[6].
You want indexes. So store that!
class myFace
{
vector<size_t> indexes_;
public:
myFace(vector<size_t>) ...
};
You don't need nPointsInFace_ because its the size of indexes_.
You can use a smaller type if you know you dont need so many, like uint16_t.
You avoid messing with pointers (and shared_ptr which is overkill for single 3D points).
You can do checked accesses.
Probably the easiest answer is to change your vector of points to a vector of pointers to points. Something like this:
vector <std::shared_ptr<MyPoint>> vectorOfPoints;
for (int i = 0; i < 10 ; i++)
{
vectorOfPoints.push_back(std::make_shared<MyPoint>(1,2,3));
}
Now you can very easily just cherry pick whichever points you want to pass to your myFace constructor. Using managed pointers like std::shared_ptr is an all-or-nothing proposition.
What if I put something like
class myFace
{
public:
// Constructor
myFace(int, vector<myPoint*>);
// Destructor
virtual ~myFace(){};
protected:
private:
int nPointsInFace_;
vector<myPoint*> refToPointsThatMakeUpThisFace_;
};
After initializing the vectorOfPoints. If I can
std::vector<Point*> listOfPoints (4);
listOfPoints[0] = vectorOfPoints[0]
listOfPoints[1] = vectorOfPoints[2]
listOfPoints[2] = vectorOfPoints[5]
listOfPoints[3] = vectorOfPoints[6]
Face myFace (4, listOfPoints);
This should create a face with the address of the vectorOfPoints, no?
More classes will have pointers the vectorOfPoints, is makes sense to use a shared_ptr, right?
Related
I have a class and another class with class member of 2d array from the first class type.
and I need a function that returns that class member.
class Piece
{
// something is implemented here/
};
class Board
{
private:
Piece* _pieces[8][8];
public:
Piece*** getPieces()
{
return _pieces;
}
}
but that's not working.
This is a quick version of your class I made to allow the passing of the 2d array to work.
class Board
{
private:
Piece ** _pieces = new Piece*[8];
public:
Board()
{
for(int i = 0; i<8; i++)
_pieces[i] = new Piece[8];
}
Piece** getPieces()
{
return _pieces;
}
~Board()
{
for(int i = 0; i<8; i++) delete [] _pieces[i];
delete [] _pieces;
}
};
You could std::array to create 2D array of pointers if you have access to C++11/14/17, it's a lot cleaner and expressive than using the build in array that decay to a ptr.
What follows is an example of how you create and return from Booard a 8x8 2D array of pointers to Pieces.
#include <array>
class Piece
{
// something is implemented here/
};
using Pieces=std::array<std::array<Piece*,8>,8>;
class Board
{
private:
Pieces _pieces;
public:
const Pieces& getPieces()
{
return _pieces;
}
};
As suggested by #Galik in comment, you should use std::arrays here, because the sizes are constant expressions.
It is not really mandated by the standard, but for common implementations, a std::array<std::array<T,i>,j> does have a true T[i][j] 2D array as underlying data - said differently, consecutive rows use adjacent memory. std::vector on another hand acts more as an array of pointers and data of consecutive rows are generally not adjacent in memory.
Code could become:
class Board
{
private:
std::array<std::array<Piece*, 8>, 8> _pieces;
public:
std::array<std::array<Piece*, 8>, 8>& getPieces()
{
return _pieces;
}
}
But this is still poor design, because it unnecessarily exposes the underlying implementation, so you really should think twice on what should be the public methods for the Board class.
for example,
int a[3][6];
int **p=a; // it's wrong
You should use pointer like this:
int (*p)[6];
p=a;
my program has a function to calculate some sum, for this i need to access attributes of objects in vector:
declaration of vector:
class trilateration {
public:
...
std::vector<tip> *potential;
...
};
then in constructor its initialized:
trilateration::trilateration()
{
...
potential = new std::vector<tip>();
...
}
class tip looks like this:
class tip {
public:
double sum;
Point2d *pt;
tip();
tip(double x, double y);
virtual ~tip();
};
tip constructor:
tip::tip(double x, double y)
{
pt = new Point2d(x,y);
sum=0;
}
objects are added to vector in some function like this:
potential->push_back(tip1);
then i want to access some objects in vector like this:
void trilateration::get3points()
{
for(int i=0; i<potential->size(); ++i)
{
for(int j=0; j<potential->size(); ++j)
{
potential[i].sum=potential[i].sum+normalize(potential[i].pt,potential[j].pt);
}
}
}
while compilation im getting follwoing error:
error: ‘class std::vector<tip>’ has no member named ‘sum’
error: ‘class std::vector<tip>’ has no member named ‘pt’
how can i acess these attributes from vector?
EDIT:
after changing potential to be a member of trilateration and pt to be member of tip, program compiled but when it encounters
potential.push_back(tip1);
throws:
*** glibc detected *** ./loktest: malloc(): memory corruption: 0x00792f10 ***
Unless there are strong reasons to have pointer data members and to allocate your objects on the heap using new, don't do that.
Your code seems to use a kind of Java-style, but this is C++, not Java. Enjoy the automatic resource management of C++, and the power of C++ destructors. Just define data members without using pointers and dynamic allocations.
In class trilateration, change from vector<tip>* to vector<tip>:
class trilateration {
public:
...
// WAS std::vector<tip> *potential;
std::vector<tip> potential;
...
};
In trilateration's constructor, you don't need to create the vector dynamically; just delete the line allocating the vector with new:
trilateration::trilateration()
{
...
// REMOVED:
// potential = new std::vector<tip>();
...
}
Note that in your previous code, when you allocated the vector with new, you had to properly delete it in the destructor, and provide proper copy operations (copy constructor and copy assignment), or ban copies marking the aforementioned operations =delete.
Instead, you don't need all this complicated stuff if you have an ordinary simple non-pointer data member.
The same goes for your tip class.
Unless there is a strong reason to have a Point2d* data member, just use a Point2d (non-pointer) data member:
class tip {
public:
double sum;
// WAS: Point2d *pt;
Point2d pt; // <-- note: no pointers here
tip();
tip(double x, double y);
// NOTE: Do you really need a virtual destructor here??
virtual ~tip();
};
Change the constructor as well:
tip::tip(double x, double y)
: pt(x, y), sum(0)
{
// REMOVE:
// pt = new Point2d(x,y);
//sum=0;
}
Your code gets simplified, and you'll avoid some bugs and headaches.
Since trilateration::potential is a std::vector<tip>*, potential[i] is a std::vector<tip> located at trilateration::potential + i. This is not what you want.
for(int j=0; j<potential->size(); ++j)
{
(*potential)[i].sum=potential[i].sum+normalize((*potential)[i].pt,(*potential)[j].pt);
}
is a possible hack. But what you really want is to get rid of all those useless pointers. Make the vector a member variable of your class and stop using new where it is not 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 have a struct Creature and a struct Game. Game is a "friend" of Creature.
In game I have
vector creatures;
and I add a creature x to that vector thourgh a function called addC
void addc (Creature& c){
creatures.push_back(c);
}
Now I'm in another function "foo" that is a public method of the struct Game.
void foo (Creature& c){
...
}
In that function I need to find another creature from the vector creatures that
matches some information from Creature c.
So I made another public method in Game called fooHelper
void fooHelper (char s, int x, int y){
bool found = false;
for (int i = 0; i < creatures.size() && (!found); ++i){
Creature& c = creatures[i];
if (x == c.x && y == c.y){
c.s = s;
found = true;
}
}
}
however when I check if the second creature's "s" member is being updated, it turns out that
it is not! I don't understand what I'm doing wrong since I'm pushing by references to the vector.
and I'm getting the creature by reference from the vector.
the vector in game looks like this
struct Game{
private:
vector<Creature> creatures;
...
}
struct Creature{
private:
char s;
int x; int y;
...
}
any help would be much appreciated!
This statement:
creatures.push_back(c);
Stores a copy of c into your vector: standard containers have value semantics. If you need reference semantics, you should store pointers into your vector.
Usually it is a good idea to use smart pointers, and which one to use depends on the ownership policy of your application. In this case, based on the information I could get from your question's text, it seems reasonable to let Game be the unique owner of all Creatures in the game (and therefore the only object which is responsible for the lifetime of the owned Creatures, and in particular for destroying them when they won't be needed anymore), so std::unique_ptr should be a good choice:
#include <memory> // For std::unique_ptr
struct Game{
private:
std::vector<std::unique_ptr<Creature>> creatures;
...
};
Your member function addc() would then become:
void addc(std::unique_ptr<Creature> c)
{
creatures.push_back(std::move(c));
}
And a client would invoke it this way:
Game g;
// ...
std::unique_ptr<Creature> c(new Creature());
g.addc(std::move(c));
Your foohelper() function, on the other hand, would be rewritten into something like this:
void fooHelper (char s, int x, int y) {
bool found = false;
for (int i = 0; i < creatures.size() && (!found); ++i){
std::unique_ptr<Creature>& c = creatures[i];
if (x == c->x && y == c->y) {
c->s = s;
found = true;
}
}
}
Finally, your class Game could return non-owning raw pointers (or references) to clients requiring access to the stored creatures.
When you push your creature reference into the vector, it's making a copy. It's a vector of type "Creature", and so it's making a copy from the reference that you give it. One solution would be to keep a vector of creature pointers.
edit - this question helps explain things a little better than I was able to on why you can't have a vector of references: Why can't I make a vector of references?
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]; }
};