Статические данные в библиотеках только заголовков - программирование
Подтвердить что ты не робот

Статические данные в библиотеках только заголовков

Я разрабатываю библиотеку, которая будет состоять только из файлов заголовков. Пока что он содержит только классы, которые были в порядке. Тем не менее, я пришел к тому моменту, когда мне нужно иметь доступную в библиотеке доступную неизменную информацию в библиотеке (то есть, а не данные экземпляра экземпляра) для реализации некоторых функций. Вы, очевидно, не можете просто помещать глобальные данные в заголовочные файлы, иначе вся единица компиляции, в которой #include заголовок будет иметь определение для символа, и вы получите несколько ошибок определения во время ссылки.

Кажется, я нашел обходное решение, которое позволяет мне статические данные в классе, не добавляя блок компиляции в библиотеку, просто добавляя переменную a 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 в файлах заголовков. Мне интересно, есть ли у этого "взлома" какие-либо непредвиденные последствия, такие как каждый блок компиляции, который #include этот заголовок получает свою собственную версию array. Как и где компилятор решил поставить его?

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

4b9b3361

Ответ 1

Это хорошо. Он гарантировал, что будет только одна копия array, если функция имеет внешнюю связь, что и делает. В стандарте С++ говорится:

7.1.2/4 Статическая локальная переменная во внешней встроенной функции всегда относится к одному и тому же объекту.

Ответ 2

Другой подход...

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>
{

};