Статические переменные в методах экземпляра

Скажем, у меня есть эта программа:

class Foo {
 public:
    unsigned int bar () {
        static unsigned int counter = 0;
        return counter++;
    }
};

int main ()
{
    Foo a;
    Foo b;
}

(Конечно, этот пример не имеет смысла, поскольку я, очевидно, объявляю "counter" как частный атрибут, но это просто для иллюстрации проблемы).

Я хотел бы знать, как С++ ведет себя в такой ситуации: будет ли переменная "counter" в методе bar() одинаковой для каждого экземпляра?

Ответ 1

Да, counter будет использоваться для всех экземпляров объектов типа Foo в вашем исполняемом файле. Пока вы работаете в однопотоковой среде, он будет работать как ожидаемый, как общий счетчик.

В многопоточной среде у вас будут интересные условия гонки для отладки:).

Ответ 2

Под "быть одинаковым для каждого экземпляра" вы подразумеваете, что будет один экземпляр этой переменной, общий для каждого экземпляра класса, а затем да, это правильно. Все экземпляры класса будут использовать тот же экземпляр переменной.

Но имейте в виду, что с переменными класса вы во многих случаях должны учитывать такие вещи, как многопоточность, что представляет собой совершенно другую тему.

Ответ 3

Из языка программирования С++ (2-е издание), стр. 200, Bjarne Stroustrup:

Не используйте статические, кроме внутренних [простых] функций (§7.1.2) и классов (§10.2.4).

Ответ 4

Ваш пример был в нескольких строках от того, что вы могли бы скомпилировать и протестировать:

#include <iostream>
using namespace std;
class Foo {
 public:
    unsigned int bar () {
        static unsigned int counter = 0;
        return counter++;
    }
};

int main ()
{
    Foo a;
    Foo b;

    for (int i=0; i < 10; i++)
      cout<<i<<". "<<a.bar()<<" / "<<b.bar()<<endl;
}

Результат выглядит следующим образом:

0. 1 / 0
1. 3 / 2
2. 5 / 4
3. 7 / 6
4. 9 / 8
5. 11 / 10
6. 13 / 12
7. 15 / 14
8. 17 / 16
9. 19 / 18

Итак, да, счетчик используется для всех экземпляров.

Ответ 5

Вам просто нужно понять две вещи:

  • Статические переменные сохраняются в статической области исполняемой программы (такой же, как у глобальной переменной).
  • Область ограничена общими правилами круглых скобок. Кроме того, статические переменные имеют внутреннюю связь.