Da Frenk
Da Frenk

Reputation: 295

Iterator on class member vector not correctly dereferenced

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

Answers (3)

juanchopanza
juanchopanza

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

Christian Stieber
Christian Stieber

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

Nick
Nick

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

Related Questions