статические функции-члены и безопасность потоков

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

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

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


person Tony The Lion    schedule 06.01.2011    source источник
comment
возможный дубликат статической функции-члена и безопасности потоков   -  person Suma    schedule 06.01.2011
comment
Тони, почему ты снова задаешь тот же вопрос?   -  person Suma    schedule 06.01.2011
comment
@Suma Я проголосовал за закрытие собственного вопроса, забыл, что уже задавал это ...   -  person Tony The Lion    schedule 07.01.2011
comment
Ха-ха не понял, что дубликат этого вопроса имеет тот же OP.   -  person Abhinav Gauniyal    schedule 22.09.2016
comment
Возможный дубликат статической функции-члена и безопасности потоков   -  person Casey    schedule 10.06.2017


Ответы (4)


Нет, ты не прав.

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

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

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

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

person Stephane Rolland    schedule 06.01.2011
comment
Есть как минимум 3 способа создать объект. Х х; X * x = новый X; X * x = новый (mem) X. - person Maxim Egorushkin; 06.01.2011
comment
@Maxim, и они будут доступны только таким образом: static X x; static X* x = new X; Что означает / подразумевает ваш комментарий? это расплывчато !? - person Stephane Rolland; 06.01.2011
comment
Это: X * x = new (mem) X; может создать объект, совместно используемый потоками или процессами. И это можно сделать из статической функции-члена, что доказывает, что ваш оператор Объекты, созданные в статической функции, не используются неправильно. - person Maxim Egorushkin; 06.01.2011
comment
@Maxim, я не использую X* x = new (mem) X;, но может быть такая же проблема с _2 _..., однако в таких случаях это не будет зависеть от разницы между статической функцией и нестатической функцией, что ИМХО то, что спросил начинающий спрашивающий ибо в этом вопросе. - person Stephane Rolland; 06.01.2011
comment
@Maxim: объекты, созданные в статической функции, относятся только к локальным / автоматическим объектам. Например. void f () {int local_var; }. Я понимаю ваше замешательство, но для меня - и, я полагаю, для большинства - было совершенно очевидно, что имеется в виду (хотя это должно быть разъяснено для обучения и т. Д.). - person Fred Nurk; 06.01.2011

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

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().

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

e.g.

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);
}

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

person Michael J    schedule 06.01.2011
comment
это, безусловно, лучшее объяснение, которое я видел. Спасибо. Мне очень помогли! - person AnyOneElse; 10.09.2013
comment
Четко и ясно! Лучшее объяснение, с которым я столкнулся, по существу, спасибо за тонну! - person ADJ; 21.07.2015

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

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

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

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

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

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

person CashCow    schedule 06.01.2011

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

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

person Raphael Bossek    schedule 06.01.2011