2010-01-29 3 views
11

Скажем, у меня есть эта программа:Статические переменные в методах экземпляра

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

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

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

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

ответ

10

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

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

+0

+1 для обозначения опасностей в многопоточной среде. – Omnifarious

+0

Предполагая, что компилятор уже не справляется с этим для вас. Определение языка состоит в том, что переменная является составной для всех вызовов метода. Таким образом, это задание компилятора для обеспечения этого, поэтому в многопоточных языках (следующая версия C++) это задание компиляторов. В этой версии это зависит от интеграции компилятора с библиотекой потоков. В gcc уже есть покрытые и гарантированные, доступ к статической переменной безопасен для нескольких потоков. –

+0

@Martin York: то есть статические переменные в C++ 0x гарантированно являются потоковыми локальными? Как интересно, и это может сильно удивить некоторых людей. Как хороший счетчик экземпляров статического класса. Внезапно вы будете подсчитывать экземпляры на поток вместо этого. Я не могу поверить, что они так изменились. Ты уверен?! – Omnifarious

2

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

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

1

От программирования C++ Language (второе издание), стр 200, Бьярне Страуструп:

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

+4

Правила фантастические. __BUT__, только если используется в правильном контексте. Пользователь nieve может взять цитату в hart. Если вы хотите, чтобы вы цитировали нечто подобное, вы __must__ включаете полный контекст. –

0

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

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

Срок службы - это не жизнь программы. Это от первого использования (которое может быть никогда) до разрушения (которое является обратным порядком создания статических переменных). Инициализация ноты Alos хороша, так как она является частью функции, а не класса. –

+0

@niel .. мой плохой !! Я не видел, что – sud03r

+0

Последнее предложение касается статических переменных пространства имен. Локальные статические переменные (например, в вопросе) не имеют связи. (Нет способа ссылаться на локальные переменные из разных областей. Как бы вы ссылались на переменную, определенную в main? 'Main() :: v', например, не работает). –

1

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

#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 

Так что да, счетчик распределяется между все экземпляры.

+0

Что забавно, так это то, что ваш результат - прекрасный пример того, как работают точки последовательности и порядок выполнения, и может привести к противоречивым результатам. – Omnifarious