user5609462 user5609462 - 1 month ago 15
C++ Question

Pushing back elements in c++ std::vector, they lose information

I'm working on a pre-existing code and checking if it works.

With my greatest surprise, these basic classes are giving me troubles

typedef int Id;
typedef int BcId;

//! This class gives some common methods to all mesh objects.
class Identifier{
public:

static const UInt NVAL;

Identifier(UInt id):id_(id),bcId_(NVAL){}
Identifier(UInt id, UInt bcId):id_(id),bcId_(bcId){}

bool unassignedId()const {return id_==NVAL;}
bool unassignedBc()const {return bcId_==NVAL;}

Id id() const {return id_;}
BcId bcId() const {return bcId_;}
Id getId() const {return id_;}


protected:
Id id_;
BcId bcId_;
};


//! This class implements a 3D point, the default is z=0 => 2D point
class Point: public Identifier{
public:

static const UInt ndim = 3;

Point(): Identifier(NVAL, NVAL){coord_.resize(3);};
Point(Real x, Real y, Real z=0):Identifier(NVAL, NVAL)
{coord_.resize(3);coord_[0]=x; coord_[1]=y; coord_[2]=x;}
Point(Id id, BcId bcId, Real x, Real y, Real z=0):Identifier(id, bcId)
{coord_.resize(3);coord_[0]=x; coord_[1]=y; coord_[2]=z;}
void print(std::ostream & out) const;
Real operator[](UInt i) const {return coord_[i];}

private:
std::vector<Real> coord_;

};

void Point::print(std::ostream & out) const
{
out<<"Point -"<< id_ <<"- "<<"("<<coord_[0]<<","<<coord_[1]<<","<<coord_[2]<<")"<<std::endl<<"------"<<std::endl;
}


Now with the simplest test:

int main()
{
Point a(1,1,0,0);
Point b(2,2,0,1);
Point c(3,3,1,0);

a.print(std::cout);
b.print(std::cout);
c.print(std::cout);

std::cout<<b.getId()<<std::endl;
b.print(std::cout);

std::vector<Point> points;
points.resize(3);
points.push_back(c);
points.push_back(b);
points.push_back(a);


std::cout<<"The points are"<<std::endl;
for (int i=0; i<3; ++i)
points[i].print(std::cout);
std::cout<<std::endl;

}


I get the output:

Point -1- (0,0,0)
------
Point -2- (0,1,0)
------
Point -3- (1,0,0)
------
2
Point -2- (0,1,0)
------
The points are
Point -2147483647- (0,0,0)
------
Point -2147483647- (0,0,0)
------
Point -2147483647- (0,0,0)

Answer

The issue here is you used points.resize(3); instead of points.reserve(3);. std::vector:::resize will change to size of the vector to the size provided. If the vector grows then it insert the necessary default constructed objects. In this case that means the first 3 elements of the vector are default constructed and the 3 points you push into it are actually in index's [3, 5].

If you had called std::vector::reserve then it would have allocated the space for 3 objects but not create any default instances. That means when you push the points back the will occupy index's [0, 2]

Comments