14

我正在开发一个仅包含头文件的库。到目前为止,它只包含类,这很好。但是,我已经到了需要在库中拥有一些库范围内可访问的不变数据(即,不是类实例数据)来实现某些功能的地步。您显然不能只将全局数据放在头文件中,否则作为头文件的每个编译单元都#include将具有符号定义,并且您将在链接时遇到多个定义错误。

我似乎找到了一种解决方法,它可以让我在类中拥有静态数据,而无需通过将数据作为static函数中的变量并返回指向该数据的指针来将编译单元添加到库中:

class StaticData {
public:
    void doSomething() { /* this uses getData */ }
    void doSomethingElse() { /* this does too */ }

private:
    static int* getData() {
        static int array[] { 1, 2, 3, 4 };

        return array;
    }
};

这似乎工作正常,但我必须承认我不知道函数static数据inline在头文件中的函数中会发生什么。我想知道这个“hack”是否有任何意想不到的影响,例如#include这个头文件的每个编译单元都有自己的array. 编译器决定如何以及在哪里放置它?

另外应该注意的是,我没有使用它来实现单例反模式或任何东西。我只是用它来存储多个函数需要使用的数据(这就是为什么它不能static只存在于使用它的函数中,但即使它存在,也会提示同样的问题)。

4

2 回答 2

10

没关系。array只要函数具有外部链接,就可以保证只有一个副本,这就是这样做的。C++ 标准说:

7.1.2/4 外部内联函数中的静态局部变量始终引用同一个对象。

于 2012-09-06T17:54:05.190 回答
0

另一种方法...

template<typename> class ArrayData {
    friend class ClassWithArray;
    static int array[4];
};

class ClassWithArray :
    ArrayData<ClassWithArray>
{
public:
    void doSomething() { 
        /* this uses getData */ 
        array[0] = 1;
        array[1] = 2;
        array[2] = 3;
        array[3] = 4;
    }
    void doSomethingElse() { 
        /* this does too */ 
        array[0] = 4;
        array[1] = 3;
        array[2] = 2;
        array[3] = 1;
    }
};

int ArrayData<ClassWithArray>::array[4] = { 1, 2, 3, 4 };

通用实现

template<typename T> class ArrayDataT 
{
    friend T;
    static int array[4];
};

template<typename T>
int ArrayDataT<T>::array[4] = { 1, 2, 3 ,4 };

class DerivedFromArrayDataT :
    ArrayDataT<DerivedFromArrayDataT>
{

};
于 2017-05-18T15:22:47.803 回答