在不贴上静态图书馆类中静态成员的最佳方法是什么,而不承担定义会员在类用户上的负担?

假设我想提供这个课程:

class i_want_a_static_member
{
    static expensive_resource static_resource_;

public:
    void foo()
    {
        static_resource_.bar();
    }
};

那么班级的用户绝不能忘记在某个地方定义静态成员(如 回答了 许多 ):

// this must be done somewhere in a translation unit
expensive_resource i_want_a_static_member::static_resource_;

我在下面确实有一个答案,但它有一些缺点。有更好和/或更优雅的解决方案吗?

有帮助吗?

解决方案

C++17 及以上

使用 inline static 非动态初始化的变量:

struct Foo
{
    inline static int I = 0;
};

否则使用函数局部静态变量:

struct Foo
{
    static std::string& Bar()
    {
        static std::string S = compute();
        return S;
    }
};

C++14 及以下版本

使用函数局部静态,因为它们更容易使用。

如果由于某种原因你真的希望有一个静态的 数据成员, ,那么你可以使用模板技巧:

template <typename T = void>
struct Foo
{
     static int I = 0; // inline initialization only for simple types.
};

template <typename T>
int Foo<T>::I;

关于本地静态

对于需要动态初始化的资源,最好使用本地静态。

通常,动态初始化文件范围或类范围静态的顺序是未定义的,当您尝试读取未初始化的静态作为另一个静态的初始化的一部分时,会导致静态初始化顺序失败。本地静态通过在首次使用时延迟初始化来解决该问题。

然而,使用本地静态数据会产生一些轻微的开销。从 C++11 开始,初始化需要是线程安全的,这通常意味着任何访问都由原子读取和良好预测的分支进行门控。

其他提示

我自己的解决方案是使用模板化持有者类,因为静态成员在模板中工作正常,并使用此持有者作为基类。

template <typename T>
struct static_holder
{
    static T static_resource_;
};

template <typename T>
T static_holder<T>::static_resource_;
.

现在使用持有者类:

class expensive_resource { /*...*/ };

class i_want_a_static_member : private static_holder<expensive_resource>
{
public:
    void foo()
    {
        static_resource_.bar();
    }
};
.

但由于在持有者类中指定了成员的名称,因此您不能使用相同的持有者以获得多个静态成员。

as c ++ 17.您现在可以使用内联变量来执行以下操作:

static const inline float foo = 1.25f;
.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top