Статические функции элементов и безопасность потока
Объекты и переменные, созданные в статической функции-члене, не считаются "локальными", как в функции-члене, так что теперь они могут быть разделены между несколькими потоками правильно?
Если у вас есть функция-член, которая создает какой-то объект, это будет локально для потока и, следовательно, не является общим.
Правильно ли я это говорю?
Ответы
Ответ 1
Нет, вы не правы.
Объекты, созданные в статической функции , не являются совместно, и это также относится к любым нормальным функциям.
Объекты могут быть разделены, хотя если они объявлены самими статическими, и это не зависит, является ли эта функция статической или нет.
void myFunc()
{
static MyObject o;
o.CallMethod(); // here o is shared by all threads calling myFunc
}
Когда объект объявляется статическим, он выглядит так, как если бы объект был глобальной переменной, но был видимым только в области функции, в которую он был объявлен.
Ответ 2
Рассмотрим этот класс
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);
}
Надеюсь, что это поможет.
Ответ 3
Нет, вы не правы. И да, С++ очень сильно злоупотребляет словом "статический".
Статическая переменная-член класса, конечно же, является глобальной с классом, действующим как область пространства имен и с некоторыми различиями привилегий доступа, если она является частной или защищенной (к ней может быть доступ только класс).
Однако статическая функция-член класса похожа на регулярную свободную функцию (не член класса) и имеет свои локальные переменные каждый раз, когда она вызывается.
Единственное реальное различие между функцией статического члена класса и регулярной бесплатной функцией, кроме соглашения об именовании, заключается в том, что он имеет доступ к закрытым членам класса (и для этого нужен внешний "экземпляр" ).
Кроме того, статическая функция-член класса может быть вызвана из шаблона с параметром шаблона переменной, вызывая то, что обычно называют "полиморфизмом времени компиляции" и обычно используется в метапрограммировании.
Статическая "локальная" переменная в любой функции является одним экземпляром, с другой стороны, также немного похожа на глобальную и чувствительна к проблемам конфликтов потоков, поскольку два потока, вызывающие функцию, получают доступ к одному экземпляру.
Ответ 4
Не имеет значения, является ли функция статической или нет (метод класса). Только автоматические переменные можно рассматривать как локальные функции. Если у вас есть адрес этих данных, вы можете получить к нему доступ.
Вы можете использовать, например. поток-локальное хранилище, чтобы назначить ваш вывод в выделенный поток.