Reputation: 295
I am having a class called Domain, which has a protected member std::vector
called
itsVec
. The vector is accessible through getVec()
.
In main()
it works fine when I directly address the elements via
getVec()[i]
. However, when I try using an iterator, the pointer to the first
element seems to not getting initialized correctly. Oddly, using an iterator on the itsVec
in the class constructor works like a charm.
The code
#include<iostream>
#include <vector>
class Domain
{
public:
/* ==================== LIFECYCLE ======================================= */
Domain ( ) {}; /* constructor */
Domain ( unsigned int , const unsigned int * ) ; /* custom constructor */
Domain ( const Domain &other ); /* copy constructor */
~Domain ( ) {}; /* destructor */
/* ==================== ACCESSORS ======================================= */
unsigned int getDim() const {return itsDim;}
std::vector<unsigned int> getVec() const {return itsVec;}
protected:
/* ==================== DATA MEMBERS ======================================= */
unsigned int itsDim;
std::vector<unsigned int> itsVec;
}; /* ----- end of class Domain ----- */
Domain::Domain( unsigned int dim, const unsigned int *externVec)
{
itsDim = dim;
for ( size_t j = 0; j < dim ; j++ )
itsVec.push_back(externVec[j]);
std::vector<unsigned int>::const_iterator i_vec = itsVec.begin();
// iterator access works
for ( ; i_vec != itsVec.end(); i_vec++)
std::cout<<"Iterator in constructor: " << (*i_vec) << std::endl;
std::cout<<std::endl;
} /* ----- end of constructor ----- */
/*-----------------------------------------------------------------------------
* Main
*-----------------------------------------------------------------------------*/
int main ()
{
const unsigned int kVec[3] = { 1, 2, 3 };
Domain k(3,kVec);
size_t i = 0;
// direct access works
for( ; i<3 ; i++)
std::cout << "Vec direct: " << k.getVec()[i] << std::endl;
std::cout << std::endl;
// iterator access FAILS for the first element
std::vector<unsigned int>::const_iterator it_vec = k.getVec().begin();
for ( ; it_vec != k.getVec().end(); it_vec++)
std::cout<<"Vec iterator " << (*it_vec) << std::endl;
return 0;
} /* ---------- end of function main ---------- */
Compiled with g++ main.cc -o test
results in
$ ./test
Iterator in constructor: 1
Iterator in constructor: 2
Iterator in constructor: 3
Vec direct: 1
Vec direct: 2
Vec direct: 3
Vec iterator 140124160
Vec iterator 2
Vec iterator 3
Testing on another machine gave:
Vec iterator 0
Vec iterator 0
Vec iterator 3
Is the way I'm returning the vector through getVec()
wrong. Is the
iterator handled incorrectly? I have no clue, whats wrong here or how to fix it.
Any help is highly appreciated,
Da Frenk
Upvotes: 3
Views: 523
Reputation: 227618
Your getVec()
method returns the vector by value, which means that each time you call getVec()
you get a new copy of the vector, so when you iterate, your begin()
and end()
iterators are incompatible. They belong to two different vectors.
You can fix this either by returning a reference to the vector:
const std::vector<unsigned int>& getVec() const {return itsVec;}
or extending your class to return the begin and end iterators of the vector.
class Domain
{
public:
std::vector<unsigned int>::iterator begin() { return itsVec.begin(); }
std::vector<unsigned int>::iterator end() { return itsVec.end(); }
std::vector<unsigned int>::const_iterator begin() const { return itsVec.begin(); }
std::vector<unsigned int>::const_iterator end() const { return itsVec.end(); }
std::vector<unsigned int>::const_iterator cbegin() const { return itsVec.begin(); }
std::vector<unsigned int>::const_iterator cend() const { return itsVec.end(); }
// ... other methods
};
Upvotes: 1
Reputation: 12496
The problem is that you are returning a COPY of the vector, which gets discarded right away, leaving you with an iterator that doesn't point anywhere.
You probably want to return a reference, or a const reference.
Upvotes: 1
Reputation: 25828
You are returning a copy of the vector rather than a reference and so you are not matching the iterators correctly. The iterator you obtain from begin()
is from a different copy of your internal vector to the one you obtain from end()
Rather than returning a copy of the internal vector you can return a reference by changing the function prototype to:
const std::vector<unsigned int>& getVec() const {return itsVec;}
Upvotes: 2