Организация статических данных в C ++ - PullRequest
3 голосов
/ 24 сентября 2011

Я работаю над некоторым встроенным программным обеспечением, в котором есть некоторая статическая информация о «продуктах».Поскольку информация для определенного продукта никогда не изменяется во время выполнения, я хотел бы инициализировать эти структуры данных во время компиляции, чтобы сэкономить место в стеке / куче.

Я создал класс Product для данных, намереваясьсоздать огромный массив всех продуктов в системе, а затем выполнить поиск в этой структуре, но я не совсем понял, как заставить его работать.Массивы доставляют мне массу неприятностей.Какой-то псевдо-код:

class Product {
    int m_price;
    int m_availability[]; // invalid, need to set a size
    ... etc

    // Constructor grabbing values for all members
    Product(int p, int a[], ...);
}

static const Product products[] = 
{
    Product(99, {52,30,63, 49}, ...), // invalid syntax
    ...                    
}                     

Есть ли способ заставить что-то подобное работать?Единственное, о чем я могу думать, это организовать по атрибутам и пропустить весь объект Product.Я чувствую, что это усложнит понимание и поддержание всего этого.

Есть ли у кого-нибудь какие-либо предложения о том, как мне лучше организовать такие данные?

Спасибо.

Ответы [ 4 ]

4 голосов
/ 24 сентября 2011

Статический массив конструкций старой школы в стиле C звучит как идеальное соответствие вашим требованиям. Инициализирует во время компиляции, ноль накладных расходов во время выполнения, без использования стека или кучи. Не случайно C по-прежнему является основным игроком во встроенном мире.

Итак (один рецепт - множество возможностей для изменения деталей);

// in .h file
    class Product {
    public: // putting this first means the class is really a struct
        int m_price;
        int m_availability[4]; 
        //.... (more)
    };
    extern const Product product_array[];
    extern const int     product_array_nbr;

// in .cpp file
    const Product product_array[] =
    {
        {
             23,
             {56,1,2,4},
             //....(more)
        },
        {
             24,
             {65,1,2,4},
             //....(more)
        },
        //....(more)
    };

    const int product_array_nbr = sizeof(product_array)/sizeof(product_array[0]);
2 голосов
/ 24 сентября 2011

Пару лет назад, когда я работал во встроенных системах, нам нужно было явно контролировать распределение памяти наших структур.

Представьте себе этот тип структуры:

.h file

template<class T,uint16 u16Entries>
class CMemoryStruct
{
public:
    /**
    *Default c'tor needed for every template
    */
    CMemoryStruct(){};
    /**
    *Default d'tor
    */
    ~CMemoryStruct(){};
    /**
    *Array which hold u16Entries of T objects. It is defined by the two template parameters, T can be of any type
    */
    static T aoMemBlock[u16Entries];
    /**
    *Starting address of the above specified array used for fast freeing of allocated memory
    */
    static const void* pvStartAddress;
    /**
    *Ending address of the above specified array used for fast freeing of allocated memory
    */
    static const void* pvEndAddress;
    /**
    *Size of one T object in bytes used for determining the array to which the necessary method will be invoked
    */
    static const size_t sizeOfEntry;
    /**
    *Bitset of u16Entries which has the same size as the Array of the class and it is used to specify whether
    *a particular entry of the templated array is occupied or not
    */
    static std::bitset<u16Entries> oVacancy;
};


/**
*Define an array of Type[u16Entries]
*/
template<class Type,uint16 u16Entries> Type CMemoryStruct<Type,u16Entries>::aoMemBlock[u16Entries];
/**
*Define a const variable of a template class
*/
template<class Type,uint16 u16Entries> const void* CMemoryStruct<Type,u16Entries>::pvStartAddress=&CMemoryStruct<Type,u16Entries>::aoMemBlock[0];
template<class Type,uint16 u16Entries> const void* CMemoryStruct<Type,u16Entries>::pvEndAddress=&CMemoryStruct<Type,u16Entries>::aoMemBlock[u16Entries-1];
template<class Type,uint16 u16Entries> const size_t CMemoryStruct<Type,u16Entries>::sizeOfEntry=sizeof(Type);
/**
*Define a bitset inside a template class...
*/
template<class Type,uint16 u16Entries> std::bitset<u16Entries> CMemoryStruct<Type,u16Entries>::oVacancy;

В зависимости от вашего компилятора и среды вы можете манипулировать областью статического размещения.В нашем случае мы перенесли это в ПЗУ, которого было много.Также обратите внимание, что в зависимости от вашего компилятора, т.е. компиляторов Greenhills, вам может понадобиться использовать ключевое слово export и определить статические члены в файле .cpp.

Вы можете использовать начальный и конечный указатели для навигации по данным.Если ваш компилятор поддерживает полный STL, вы можете использовать std :: vectors с пользовательскими распределителями и перегружать новые операторы, которые сохранят вашу память где-то еще, кроме стека.В нашем случае новые операторы были перегружены таким образом, что все выделение памяти было сделано на предопределенных структурах памяти.

Надеюсь, я дал вам идею.

1 голос
/ 24 сентября 2011

В C ++ 98/03 вы не можете инициализировать массивы в инициализаторе конструктора.

В C ++ 11 это было исправлено с равномерной инициализацией:

class Product
{
  int m_availability[4]; 
public:
  Product() : m_availability{52,30,63, 49} { }
};

Если вам необходимо предоставить данные в конструкторе, используйте vector вместо:

class Product
{
  const std::vector<int> m_availability; 
public:
  Product(std::initializer_list<int> il) : m_availability(il) { }
};

Использование:

extern const Product p1({1,2,3});
0 голосов
/ 24 сентября 2011

Память для статических переменных все еще зарезервирована, когда код фактически выполняется - вы не будете экономить место в стеке. Возможно, вы захотите рассмотреть использование векторов вместо массивов - их легче передавать и обрабатывать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...