0

I have this code. scores is a field in HiscoreTable of type std::vector<reference_wrapper<Record>>

void HiscoreTable::replaceRecord(Record rec)
{
  bool found = false;
  for (reference_wrapper<Record> r : scores) {
    if (r.get().name == rec.name) {
      r = rec;
      found = true;
      break;
    }
  }
  if (!found) {
    scores.push_back(rec);
  }
}

And if I try to do for(reference_wrapper<Record> r : scores) cout << r.get() << endl;, a bad_alloc is thrown. Is it because r is not a Record& but a reference_wrapper<Record> and therefore I cannot assign a Record to it? I thought reference_wrapper<Record>::operator= was overloaded to allow such a thing?

EDIT: Turns out it was a problem in my destructor, where the printing loop was located. At some point, I passed a HiscoreTable in to a helper function by value, and when it got destructed at the end of the helper function, it invalidated the callsite's HiscoreTable. I don't know why printing would break a reference, but I guess that's what happened.

Matt G
  • 1,661
  • 19
  • 32
  • 5
    Why not use a debugger, enable break on all exceptions, and backtrace the stack to the point of origin in your code? Would be better than just speculating. – Captain Obvlious Nov 30 '14 at 01:26

1 Answers1

1

For starters, you are creating a reference to a local object.

void HiscoreTable::replaceRecord(Record rec) { // 'rec' passed by value.
    bool found = false;
    for (reference_wrapper<Record> r : scores) {
        if (r.get().name == rec.name) {
        r = rec; // Reference to local object 'rec'.

        /* ... */

} // 'rec' is destroyed and any reference to it will become dangling.

The assignment operator of std::reference_wrapper will replace the internal "reference" with the one passed as argument, e.g.

r = rec; // Reference wrapper 'r' will contain pointer to 'rec'.

Instead pass rec by reference. Also for the replacement to stick, you will need to change the type of r in the for-loop to be a reference. Otherwise you are assigning to a local copy.

for (reference_wrapper<Record>& r : scores) { // Type changed to reference.
    /* ... */
}
Felix Glas
  • 15,065
  • 7
  • 53
  • 82