Velocity Reviews > C++ > Problem storing tvmet vector objects in an stl vector container

# Problem storing tvmet vector objects in an stl vector container

alexjcollins@gmail.com
Guest
Posts: n/a

 09-08-2008
The following program demonstrates the problem:

#include <vector>
#include <iostream>
#include <tvmet/Vector.h>

typedef tvmet::Vector<double, 3> Vector3d;

class Mesh
{
public:
private:
std::vector<Vector3d> m_tVertices;
};

{ m_tVertices.push_back(tVertex);
return &m_tVertices.back();
}

int main()
{
Mesh tMesh;
Vector3d* pVertex0 = tMesh.addVertex(Vector3d(-1, 1, 1));
std::cout << "Vertex0: " << (*pVertex0)(0) << ", " << (*pVertex0)
(1) << ", " << (*pVertex0)(2) << std::endl;
Vector3d* pVertex1 = tMesh.addVertex(Vector3d( 1, 1, 1));
std::cout << "Vertex0: " << (*pVertex0)(0) << ", " << (*pVertex0)
(1) << ", " << (*pVertex0)(2) << std::endl;
std::cout << "Vertex1: " << (*pVertex1)(0) << ", " << (*pVertex1)
(1) << ", " << (*pVertex1)(2) << std::endl;
return 0;
}

Which gives the following output:

Vertex0: -1, 1, 1
Vertex0: 0, 1, 1
Vertex1: 1, 1, 1

Vertex0: -1, 1, 1
Vertex0: -1, 1, 1
Vertex1: 1, 1, 1

It is interesting to note that the code behaves correctly if an stl
list is used instead. I can't work out why this is not working, and it
seems like such a trivial program! Could anyone explain to me what is
wrong?

alexjcollins@gmail.com
Guest
Posts: n/a

 09-08-2008
On Sep 8, 9:17*pm, Victor Bazarov <(E-Mail Removed)> wrote:
> (E-Mail Removed) wrote:
> > The following program demonstrates the problem:

>
> > #include <vector>
> > #include <iostream>
> > #include <tvmet/Vector.h>

>
> > typedef tvmet::Vector<double, 3> Vector3d;

>
> > class Mesh
> > {
> > public:
> > * * Vector3d* addVertex(const Vector3d& tVertex);
> > private:
> > * * std::vector<Vector3d> m_tVertices;
> > };

>
> > Vector3d* Mesh::addVertex(const Vector3d& tVertex)
> > { * m_tVertices.push_back(tVertex);
> > * * return &m_tVertices.back();
> > }

>
> > int main()
> > {
> > * * Mesh tMesh;
> > * * Vector3d* pVertex0 = tMesh.addVertex(Vector3d(-1, 1, 1));
> > * * std::cout << "Vertex0: " << (*pVertex0)(0) << ", " << (*pVertex0)
> > (1) << ", " << (*pVertex0)(2) << std::endl;
> > * * Vector3d* pVertex1 = tMesh.addVertex(Vector3d( 1, 1, 1));
> > * * std::cout << "Vertex0: " << (*pVertex0)(0) << ", " << (*pVertex0)
> > (1) << ", " << (*pVertex0)(2) << std::endl;
> > * * std::cout << "Vertex1: " << (*pVertex1)(0) << ", " << (*pVertex1)
> > (1) << ", " << (*pVertex1)(2) << std::endl;
> > * * return 0;
> > }

>
> > Which gives the following output:

>
> > Vertex0: -1, 1, 1
> > Vertex0: 0, 1, 1
> > Vertex1: 1, 1, 1

>
> > Instead of the expected output:

>
> > Vertex0: -1, 1, 1
> > Vertex0: -1, 1, 1
> > Vertex1: 1, 1, 1

>
> > It is interesting to note that the code behaves correctly if an stl
> > list is used instead. I can't work out why this is not working, and it
> > seems like such a trivial program! Could anyone explain to me what is
> > wrong?

>
> 'push_back' *is allowed* to invalidate all pointers and iterators to any
> of the vector's elements. *So, storing 'pVertex0' is probably a bad idea
> if you intend to grow the vector (matrix).
>
> V
> --

Thanks, that makes sense.
Is push_back allowed to invalidate pointers when using a list?

Juha Nieminen
Guest
Posts: n/a

 09-08-2008
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> Is push_back allowed to invalidate pointers when using a list?

AFAIK std::list is guaranteed to preserve pointers to existing
elements valid even if new elements are added.

If you need random access (and more efficient memory usage) you might
want to consider using std::deque instead of std::vector. The former
behaves mostly like std::vector, but pointers are not invalidated.