20

在静态成员函数中创建的对象和变量不像在成员函数中那样被视为“本地”,因此它们现在可以在多个线程之间共享,对吗?

而如果您有一个创建某个对象的成员函数,这将是线程本地的,因此它是非共享的。

我这样说对吗?

4

4 回答 4

45

考虑这个类

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是一个静态变量。在类 CData 的所有使用之间存在一个共享实例,d因此可能需要同步。它可以很容易地从静态函数中使用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);
}

希望有帮助。

于 2011-01-06T18:48:19.013 回答
24

不,你不正确。

在静态函数中创建的对象不共享,任何普通函数也是如此。

如果对象本身被声明为静态,则可以共享对象,并且不取决于函数是否为静态。

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

当一个对象被声明为静态时,就好像该对象是一个全局变量,但仅在声明它的函数范围内可见。

于 2011-01-06T16:37:19.730 回答
3

不,你不正确。是的,C++ 确实过度使用了“静态”这个词。

静态类成员变量当然是全局的,类充当命名空间范围,如果它是私有的或受保护的(只能由类访问),则具有一些访问权限差异。

然而,静态类成员函数就像普通的自由函数(不是类成员),每次调用时都有自己的局部变量。

除了命名约定之外,静态类成员函数和常规自由函数之间唯一真正的区别是它可以访问类的私有成员(并且需要一个的外部“实例”)。

此外,可以从具有可变模板参数的模板调用静态类成员函数,调用通常称为“编译时多态性”的东西,通常用于元编程。

任何函数中的静态“局部”变量都是单实例,另一方面,也有点像全局变量,并且对线程争用问题很敏感,因为调用该函数的两个线程访问同一个实例。

于 2011-01-06T16:37:09.890 回答
1

函数是否是静态的(类方法)都没有关系。只有自动变量才能被视为函数的局部变量。如果您有这些数据的地址,则可以访问它。

您可以使用例如线程本地存储将您的输出分配给专用线程上下文。

于 2011-01-06T16:36:12.677 回答