简体   繁体   中英

C++ discrepancies in vector of pointers to objects

I have a problem in a piece of code I'm writing. I've boiled it down to this example which produces the same results (in principal).

Basically I've got a vector of pointers to Objects that I come across in one class, and pass to another. I then notice that by going through this vector with an iterator I come across NULL or garbage values, whereas using a traditional for-loop runthrough everything's fine.

Here's the code:

#include <iostream>
#include <vector>

using namespace std;

class MyObject
{
  public:
    int a;
    int b;

    MyObject(int _a, int _b)
    {
      a = _a;  b = _b;
    }
};

class Builder
{
  public:
    Builder() {
      obj_vector.push_back(new MyObject(1, 2));
      obj_vector.push_back(new MyObject(3, 4));     
    }

    vector<MyObject*> getObjectVector() { return obj_vector; }

  private:
     vector<MyObject*> obj_vector;  
};

class MyObjectHolder
{
  public:
    MyObjectHolder()
    {
      Builder builder;
      obj_vector = builder.getObjectVector();
    }

    vector<MyObject*> getObjectVector() { return obj_vector; }

  private:
    vector<MyObject*> obj_vector;

};

int main()
{
  MyObjectHolder holder;

    for (vector<MyObject*>::iterator itr = holder.getObjectVector().begin(); itr != holder.getObjectVector().end(); ++itr)
    {   
      if ((*itr) == NULL) {
        cout << "NULL" << endl;         
      }
      else
      {
        cout << (*itr)->a << "\t" << (*itr)->b << endl;
      } 
    }   
    cout << endl;

    for (unsigned int i = 0; i < holder.getObjectVector().size(); i++)
    {       
      if (holder.getObjectVector()[i] == NULL)
        cout << "NULL" << endl;
      else
        cout << holder.getObjectVector()[i]->a << "\t" << holder.getObjectVector()[i]->b << endl;
    }

    return 0;
}

And the output of this program is:

0   0
3   4

1   2
3   4

So I'm wondering why the iterator object produces garbage values. In other instances the iterator does equal NULL. I'm guessing it has something to do with some of the bbjects going out of scope while being passed around between objects, but I can't figure out where or why.

Thanks

holder.getObjectVector() returns a new vector . So holder.getObjectVector().begin() and holder.getObjectVector.end() are unrelated, as exists in for loop.

Changing getObjectVector() to return a reference would correct this:

vector<MyObject*>& getObjectVector() { return obj_vector; }

EDIT:

An alternative would be to arrange to call getObjectVector() once before the for loop and store the result and it would not be necessary to return a reference:

vector<MyObject*> objs = holder.getObjectVector();
for (vector<MyObject*>::iterator itr = objs.begin(); itr != objs.end(); ++itr)
{
    ...
}

Correct me if I am wrong, but i think that in your code :

class MyObjectHolder
{
  public:
    MyObjectHolder()
    {
      Builder builder; <------ this is on local stack (i.e. gone on constructor exit)
      obj_vector = builder.getObjectVector();
    }

    vector<MyObject*> getObjectVector() { return obj_vector; }

  private:
    vector<MyObject*> obj_vector;  <---- so this points to random dynamic memory

};

and it just happens that sometimes the memory location isn't used by other code on the stack before its referenced.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM