CS253: Software Development with C++

Spring 2018

Iterator Invalidation

See this page as a slide show

CS253 Iterator Invalidation

Invalidation

Consider this poor code:

int *p = new int(42);
cout << "Before: " << *p << '\n';
delete p;
cout << "After:  " << *p << '\n';
Before: 42
After:  0

More Invalidation

Another way to invalidate a pointer:

string *p;
{
    string name = "John Jacob Jingleheimer Schmidt";
    p = &name;
    cout << p->size() << ' ' << *p << '\n';
}
cout << p->size() << ' ' << *p << '\n';
31 John Jacob Jingleheimer Schmidt
31 ␀␀␀␀␀␀␀␀ob Jingleheimer Schmidt

Iterator invalidation

vector<int> v = {253};
vector<int>::iterator it = v.begin();

cout << "Before: " << *it << '\n';

for (int i=1; i<1000; i++)
    v.push_back(i);

cout << "After:  " << *it << '\n';
Before: 253
After:  -1782429768

Lipstick on a pig

Using auto makes the code prettier, but no better:

vector<int> v = {253};
auto it = v.begin();

cout << "Before: " << *it << '\n';

for (int i=1; i<1000; i++)
    v.push_back(i);

cout << "After: " << *it << '\n';
Before: 253
After: 1734121400

Reservation

Using .reserve() pre-allocates memory:

vector<int> v = {253};
v.reserve(1005);
auto it = v.begin();

cout << "Before: " << *it << '\n';

for (int i=1; i<1000; i++)
    v.push_back(i);

cout << "After:  " << *it << '\n';
Before: 253
After:  253

How often?

How often does re-allocation happen? We can find out, for any particular implemention:

vector<int> v;

cout << v.size() << ' ' << v.capacity() << '\n';
for (int i=1; i<1000; i++) {
    auto before = v.capacity();
    v.push_back(i);
    auto after = v.capacity();
    if (before != after)
        cout << v.size() << ' ' << v.capacity() << '\n';
}
0 0
1 1
2 2
3 4
5 8
9 16
17 32
33 64
65 128
129 256
257 512
513 1024

How often?

Similarly, because a std::string is not much more than a vector<char>:

string s;

cout << s.size() << ' ' << s.capacity() << '\n';
for (int i=1; i<10000; i++) {
    auto before = s.capacity();
    s += 'x';
    auto after = s.capacity();
    if (before != after)
        cout << s.size() << ' ' << s.capacity() << '\n';
}
0 15
16 30
31 60
61 120
121 240
241 480
481 960
961 1920
1921 3840
3841 7680
7681 15360

Order Calculation

Pre-allocation helps

Again, if we know how many items we’re going to add, we can .reserve() the space:

vector<int> v;
v.reserve(900);

cout << v.size() << ' ' << v.capacity() << '\n';
for (int i=1; i<1000; i++) {
    auto before = v.capacity();
    v.push_back(i);
    auto after = v.capacity();
    if (before != after)
        cout << v.size() << ' ' << v.capacity() << '\n';
}
0 900
901 1800

User: Guest

Check: HTML CSS
Edit History Source

Modified: 2018-04-04T09:53

Apply to CSU | Contact CSU | Disclaimer | Equal Opportunity
Colorado State University, Fort Collins, CO 80523 USA
© 2018 Colorado State University
CS Building