C++ Vectors of Objects and Pointers -


this contrived example illustrates problem i've encountered. basically, create vector of objects, vector of pointers objects, print pointers , dereferenced objects.

#include <vector> #include <iostream>  using namespace std;  namespace {     struct myclass {         int* myint;         myclass(int* i) : myint(i) {}     };      struct mybigclass {         vector<myclass> allmyclassrecords;  // keep myclass instances         vector<int> theints;          void loadmyclasses();         void readmyclasses();         mybigclass() {}     };  }  void mybigclass::loadmyclasses() {     (int = 0; < 10; ++i) {         theints.push_back(i);   // create int         int *j = &theints[theints.size() - 1];  // create pointer new int         allmyclassrecords.push_back(myclass(j));    // create myclass using pointer     } }  void mybigclass::readmyclasses() {     (vector<myclass>::iterator = allmyclassrecords.begin();             != allmyclassrecords.end(); ++it)         cout << it->myint << " => " << *(it->myint) << endl; }  int main() {     mybigclass mbc;      mbc.loadmyclasses();     mbc.readmyclasses(); } 

basically, want create vector of pointers vector of ints. problem code prints out following:

0x97ea008 => 159293472 0x97ea02c => 1 0x97ea040 => 2 0x97ea044 => 3 0x97ea078 => 4 0x97ea07c => 5 0x97ea080 => 6 0x97ea084 => 7 0x97ea0d8 => 8 0x97ea0dc => 9 

it appears work expected except first value, garbage in memory. why first value affected? if code broken, why broken first pointer inserted?


update: i'm compiling using g++ on ubuntu. far i'm doing, i'm creating compiler analysis pass. myclass objects hold information instructions, want update when locate registers. register number indexes vector of vectors, particular register number have vector of myclass*s. thus, if register found, myclass pointers in vector used update myclass object held in separate myclass vector. because i'm accumulating both instruction info stored in myclass objects , register info must follow myclass pointers, can't create entire myclass vector first without creating separate pass, i'd avoid.


update2: pictures...

pass progress           inserts...   instrecs (theint)  , updates...  updateptrs (myclass)  ----------------------              ------------------                  ----------------------- | => i1: uses r0, r1 |              | instrec i1 |                  | r0: instrec i1* | |    i2: uses r0, r2 |              ------------------                  | r1: instrec i1* | ----------------------                                                  ----------------------- 

first pass inserts instrec info i1. creates pointers new instrec indexed register number. r0 here vector of 1 element points instrec i1, if r0 ever encountered again in subsequent instruction, instrec i1 updated.

pass progress           inserts...   instrecs (theint)  , updates...  updateptrs (myclass)  ----------------------              ------------------                  ----------------------- |    i1: uses r0, r1 |              | instrec i1 |                  | r0: instrec i1* | | => i2: uses r0, r2 |              | instrec i2 |                  |     instrec i2* | ----------------------              ------------------                  | r1: instrec i1* |                                                                         | r2: instrec i2* |                                                                         ----------------------- 

similarly, second entry inserted instrecs , pointers added updateptrs structure. since i2 uses r0, instrec pointer pushed r0 vector. not shown this: when detected i2 uses r0, pass looks in updateptrs structure @ r0 vector of pointers, follows each pointer instrec entry, , updates instrec new info.

hopefully makes i'm trying little bit clearer. i've implemented suggestion first proposed @merickowa of using instrec vector indices rather instrec pointers (since once instrecs added array, never move), , seems working now.

its not broken on first one, happens 1 gets corrupted. if notice, pointers 0 through 7 pointing different chunks of memory when should right next each other.

std::vector can reallocate space needs dynamic objects @ time add vector , doesn't have enough capacity. can't rely on pointers (or iterators) still being valid after adding or inserting increase size.

theres many solutions like

a) can reserve space (using vector::reserve) ahead of time dynamic re-allocation doesn't occur, have know maximum number of objects you'll adding.

b) wait until objects added before getting pointers objects

c) use index object , pointer vector pair refer objects oppose object pointers directly. more work wont change (assuming you're not inserting/removing objects in beginning or middle)

d) try detect when vector has reallocated data (vector::capacity returns different value) , flush pointer vector , rebuild it

e) use different container objects doesn't reallocate on changes std::list , give random access on container of base objects, can still use vector of pointers pointers don't become invalidated. (do need random access , pointers objects?)

f) rethink design not require such pointers


Comments

Popular posts from this blog

asp.net - repeatedly call AddImageUrl(url) to assemble pdf document -

java - Android recognize cell phone with keyboard or not? -

iphone - How would you achieve a LED Scrolling effect? -