user494085
user494085

Reputation: 336

Modifying a vector reference. What gets invalidated?

Assume I have the following code:

void appendRandomNumbers(vector<double> &result) {
    for (int i = 0; i < 10000; i++) {
        result.push_back(rand());
    }
}

vector<double> randomlist;
appendRandomNumbers(randomlist);
for (double i : randomlist) cout << i << endl;

The repeated push_back() operations will eventually cause a reallocation and I suspect a memory corruption. Indeed, the vector.push_back() documentation says that

If a reallocation happens, all iterators, pointers and references related to the container are invalidated.

After the reallocation happens, which of the scopes will have a correct vector? Will the reference used by appendRandomNumbers be invalid so it pushes numbers into places it shouldn't, or will the "correct" location be known by appendRandomNumbers only and the vector is deleted as soon as it gets out of scope?

Will the printing loop iterate over an actual vector or over a stale area of memory where the vector formerly resided?

Edit: Most answers right now say that the vector reference itself should be fine. I have a piece of code similar to the one above which caused memory corruption when I modified a vector received by reference and stopped having memory corruption when I changed the approach. Still, I cannot exclude that I incidentally fixed the real reason during the change. Will experiment on this.

Upvotes: 0

Views: 185

Answers (3)

Barry
Barry

Reputation: 303337

I think you're confused about what gets invalidated. Everything in your example is perfectly behaving code. The issue is when you keep references to data that the vector itself owns. For instance:

vector<double> v;
v.push_back(x);
double& first = v[0];
v.push_back(y);
v.push_back(z);
v.push_back(w);
cout << first;

Here, first is a reference to v's internal data - which could get invalidated by one of the push_back()s and unless you specifically accounted for the additional size, you should assume that it was invalidated so the cout is undefined behavior because first is a dangling reference. That's the sort of thing you should be worried about - not situations where you pass the whole vector itself by reference.

Upvotes: 0

Cory Kramer
Cory Kramer

Reputation: 117926

The reference vector<double> &result will be fine, the problem would be if you had something referencing the underlying memory such as

double& some_value = result[74];
result.push_back();   // assume this caused a reallocation

Now some_value is referencing bad memory, the same would occur with accessing the underlying array using data

double* values = result.data();
result.push_back();  // again assume caused reallocation

Now values is pointing at garbage.

Upvotes: 0

NathanOliver
NathanOliver

Reputation: 180925

I think you are confused on what is going on. push_back() can invalidate iterators and references that point to objects in the vector, not the vector itself. In you situation there will be no invalidation and your code is correct.

Upvotes: 1

Related Questions