Я занимаюсь разработкой библиотеки, которая будет состоять только из заголовочных файлов. Пока что он содержит только классы, что было хорошо. Тем не менее, я пришел к моменту, когда мне нужно иметь в библиотеке некоторые неизменяемые неизменяемые данные в библиотеке (то есть не данные экземпляра класса) для реализации некоторых функций. Очевидно, вы не можете просто поместить глобальные данные в заголовочные файлы или в каждую единицу компиляции, которая #include
s заголовок будет иметь определение для символа, и вы получите несколько ошибок определения во время соединения.
Кажется, я нашел обходной путь, который позволяет мне иметь статические данные в классе, не добавляя модуль компиляции в библиотеку, просто делая данные 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
s этот заголовок получает свою собственную версию array
, Как и где компилятор решает поместить его?
Также следует отметить, что я не использую это для реализации одноэлементного антипаттерна или чего-либо еще. Я просто использую его для хранения данных, которые понадобятся нескольким функциям (вот почему это не может быть static
только в функции, которая использует его, но даже если бы он это сделал, это вызвало бы тот же вопрос).
Все в порядке. Гарантируется, что будет только одна копия array
До тех пор, пока функция имеет внешнюю связь, что делает это. Стандарт C ++ гласит:
7.1.2 / 4 Статическая локальная переменная во внешней встроенной функции всегда ссылается на один и тот же объект.
Другой подход …
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>
{
};