简体   繁体   中英

“error: assignment of read-only location” in unordered_map (C++)

I have an awkward hash table (specifically, an unordered_map) with int keys and vector< vector< int >> data. I periodically need to update elements in this two-dimensional vector of ints. There's no intrinsic reason I shouldn't be able to, right? A newer g++ compiler I've switched to complains of an assignment of read-only location on the line designated below.

typedef std::tr1::unordered_map< int, vector< vector< int > > > pimap;

vector< Strain * > liveStrains;
pimap phenotypeIs;
int NUM_DEMES = 3;

...
vector< Strain * >::const_iterator lsItr;
for ( lsItr = liveStrains.begin(); lsItr != liveStrains.end(); ++lsItr ) {
 int thisP = (*lsItr)->getPhenotype();
 pimap::iterator piItr = phenotypeIs.begin();
 piItr = phenotypeIs.find( thisP );
 if ( piItr != phenotypeIs.end() ) {
   for ( int d = 0; d < NUM_DEMES; d++ ) {
      ( piItr -> second )[ thisStep ].at( d ) = (*lsItr)->getI( d );  // error here
   }
 }
}

I'm new to C++, so nothing's too obvious. Thank you for any help.


Following Tim's suggestion

I've replaced the relevant parts of code above with the following:

  pimap::iterator piItr = phenotypeIs.find( thisP );
  if ( piItr != phenotypeIs.end() ) {
    for ( int d = 0; d < NUM_DEMES; d++ ) {
      vector< vector< int > > & thisVec2 = piItr->second;
      vector<int> & thisVec = thisVec2.at( thisStep );
      int & ii = thisVec.at( d );
      ii = (*lsItr)->getI( d );
      // ( piItr -> second )[ thisStep ].at( d ) = (*lsItr)->getI( d ); // error was here
    }

This code compiles without the error and appears to run fine. Like Tim, I still don't quite understand why the fix works. The error was previously appearing with gcc version 4.1.2 20080704 (Red Hat 4.1.2-44) but not with gcc version 4.0.1 (Apple Inc. build 5465). I will try to dissect the error more carefully when I'm not under a tight deadline!

Are you sure there really are thisStep + 1 elements in every first-level vector and NUM_DEMES elements in every second-level vector?

You're not actually assigning to a map iterator, if I read correctly, so I suspect the error is in the vector access.

It may be helpful to break that last statement up into multiple statements so that only one thing is being done on each to narrow down where the problem is. eg,

Strain* strain = *lsItr;
vector<vector<int> >& vv = piItr->second;
vector<int>& v = vv[thisStep];
int& i = v.at(d);     // <-- My bet is that the error occurs here or the prev. line
i = strain->getI( d );

By the way, piItr = phenotypeIs.begin(); has no effect here, it could be simply:

pimap::iterator piItr = phenotypeIs.find( thisP );
( piItr -> second )[ thisStep ].at( d )

at() returns an iterator into the inner vector, not access to the value. What you want is

 *(( piItr -> second )[ thisStep ].at( d ))

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