2011-01-06 2 views
16

Объекты и переменные, созданные в статической функции-члене, не считаются «локальными», как в функции-члене, так что теперь они могут быть разделены между несколькими потоками правильно?статические функции-члены и безопасность потоков

Принимая во внимание, что если у вас есть функция-член, которая создает некоторый объект, это будет локально для потока, и поэтому оно не является общим.

Правильно ли я это говорю?

+0

Возможный дубликат [статическая функция элемента и безопасность потока] (http://stackoverflow.com/questions/4509850/static-member-function-and-thread-safety) – Suma

+5

Тони, почему, на земле, вы снова задав тот же вопрос? – Suma

+0

@Suma Я проголосовал за закрытие своего вопроса, забыл, что уже спросил об этом ... –

ответ

19

Вы не правы.

Объекты, созданные в статической функции , не являются, и это также относится к любым нормальным функциям.

Объекты могут использоваться совместно, если они объявлены самими статическими, и это не зависит от того, является ли эта функция статической или нет.

void myFunc() 
{ 
    static MyObject o; 
    o.CallMethod(); // here o is shared by all threads calling myFunc 
} 

Когда объект объявлен статическим, это как если бы объект был глобальным переменным, но только в видимой области видимости функции, что она объявлена ​​в.

+0

Существует не менее 3 способов создания объекта. X x; X * x = новый X; X * x = new (mem) X. –

+0

@Maxim, и они будут разделены ** только ** следующим образом: 'static X x; static X * x = new X; 'Что означает ваш комментарий/подразумевает ваш комментарий? это расплывчато! –

+0

Это: X * x = new (mem) X; может создать объект, совместно используемый между потоками или процессами. И это может быть сделано из статической функции-члена, что доказывает, что ваш оператор «Объекты, созданные в статической функции, не разделены» неправильно. –

1

Не имеет значения, является ли функция статической или нет (метод класса). Только автоматические переменные можно увидеть как local функции. Если у вас есть адрес этих данных, вы можете получить к нему доступ.

Вы можете использовать, например. thread-local storage, чтобы назначить ваш вывод выделенному контексту потока.

3

Нет, вы не правы. И да, C++ очень сильно злоупотребляет словом «статический».

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

Однако статическая функция-член класса похожа на обычную свободную функцию (не член класса) и имеет свои локальные переменные каждый раз, когда она вызывается.

Единственная реальная разница между функцией статического члена класса и обычной бесплатной функцией, кроме ее соглашения об именах, заключается в том, что она имеет доступ к закрытым членам класса (и для этого требуется внешний «экземпляр»).

Кроме того, из шаблона с переменным параметром шаблона можно вызвать функцию статического класса, вызывая так называемый «полиморфизм времени компиляции» и обычно используется в метапрограммировании.

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

39

Рассмотрим этот класс

class CData 
{ 
public: 
    static void func() 
    { 
     int a; 
     static int b; 
    } 

    int c; 
    static int d; 
}; 

int main() 
{ 
    CData::func(); 
} 

Теперь переменная a является локальным для каждого вызова func(). Если два потока одновременно называют func(), они получают разные версии a.

b является статическим локальным.Значение сохраняется между различными вызовами func(). Если два потока одновременно звонят func(), они получают доступ к той же версии b, поэтому им может потребоваться синхронизация.

c - переменная экземпляра; он привязан к конкретному экземпляру CData. func() не может получить доступ к c, за исключением трюка, который я покажу ниже.

d - статическая переменная. Существует один экземпляр d, используемый всеми способами использования CData класса, поэтому может потребоваться синхронизация. Его можно легко использовать из статической функции func().

Трюк, используемый для доступа к данным экземпляра из статической функции, заключается в передаче действительного объекта в функцию.

например.

class CData 
{ 
public: 
    static void func(CData *p) 
    { 
     int a; 
     static int b; 

     b = p->c; 
    } 

    int c; 
    static int d; 
}; 

int main() 
{ 
    CData data; 
    CData::func(&data); 
} 

Надеюсь, что это поможет.

+4

Хорошее объяснение чувак! – Meysam

+2

это, безусловно, лучшее объяснение, которое я видел. Спасибо. Помог мне много! – AnyOneElse

+1

Четкий и чистый! Лучшее объяснение я натолкнулся, к сути, спасибо тонну! – ADJ

Смежные вопросы