CS253: Software Development with C++

Spring 2022

Local Static

Show Lecture.LocalStatic as a slide show.

CS253 Local Static

Try #1

Here’s a program to generate unique student ID numbers:

unsigned long next_id() {
    unsigned long id=800000000UL;  // 🦡
    return ++id;
}

int main() {
    cout << next_id() << '\n';
    cout << next_id() << '\n';
    cout << next_id() << '\n';
}
800000001
800000001
800000001

That wasn’t very good. Of course, id got re-initialized every time that next_id() was called.

Try #2

Let’s move id out of next_id():

unsigned long id=800000000UL;  // 🦡

unsigned long next_id() {
    return ++id;
}

int main() {
    cout << next_id() << '\n';
    cout << next_id() << '\n';
    cout << next_id() << '\n';
}
800000001
800000002
800000003

Better, but now we have an evil global variable. 👹

Try #3

Let’s make id static:

static unsigned long id=800000000UL;  // 🦡

unsigned long next_id() {
    return ++id;
}

int main() {
    cout << next_id() << '\n';
    cout << next_id() << '\n';
    cout << next_id() << '\n';
}
800000001
800000002
800000003

Better in that id is only visible to this file, but that’s still semi-global. Can we improve?

Try #4

Move id back to next_id(), but leave it static.

unsigned long next_id() {
    static unsigned long id=800000000UL;
    return ++id;
}

int main() {
    cout << next_id() << '\n';
    cout << next_id() << '\n';
    cout << next_id() << '\n';
}
800000001
800000002
800000003

Hooray! Now, id is private and persistent. 👏

Summary

It’d be nice to have separate words for those distinct purposes, but standards committees are stingy with new words, and re-use old ones.

static global example

// Remember program starting time:
static const auto start = time(nullptr);

int main() {
    cout << start << '\n';
    sleep(1);
    cout << start << '\n';
}
1732267186
1732267186

Actually, in the global scope, const implies static, so the above definition is a bit redundant.

Home Directories

static local example

string homedir() {
    // Call expensive getpwnam() once, at most.
    // Segfault if the lookup fails! 😧
    static string d = getpwnam("cs253")->pw_dir;
    return d;
}
int main() {
    cout << homedir() << '\n'; // first is slow
    cout << homedir() << '\n'; // second is fast
}
/s/bach/a/class/cs253
/s/bach/a/class/cs253

Example

char foo() {
    static char id = 'A';
    cout << "foo: returning " << id << "\n";
    return id++;
}

static auto glob = foo();

int main() {
    cout << "glob = " << glob << '\n';
    for (int i=0; i<5; i++) {
        if (i>10) {
            static char zip = foo();
            cout << "zip = " << zip << '\n';
        }
        static char bar = foo();
        cout << "bar = " << bar << '\n';
    }
    return 0;
}
foo: returning A
glob = A
foo: returning B
bar = B
bar = B
bar = B
bar = B
bar = B