我正在开发一些嵌入式软件,其中有一些关于"产品的静态信息"。由于某个产品的信息在执行期间永远不会改变,我想在编译时初始化这些数据结构,以节省堆栈/堆上的一些空间。
我为数据创建了一个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
对象。我觉得这会让整个事情更难理解和维护。
有没有人对如何最好地组织这类数据有任何建议?
谢谢。
答案 0 :(得分:4)
古老的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]);
答案 1 :(得分:2)
几年前,当我在嵌入式工作时,我们需要明确控制结构的内存分配。
想象一下这种结构:
.h文件
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;
根据您的编译器和环境,您可以操纵静态分配所在的区域。在我们的例子中,我们把它移到了很多的ROM上。另请注意,根据您的编译器(即Greenhills编译器),您可能需要使用export关键字并将静态成员定义为.cpp文件。
您可以使用开始和结束指针来浏览数据。如果您的编译器支持完整的STL,您可能希望将std :: vectors与自定义分配器和重载的新运算符一起使用,这样可以将内存保存到堆栈以外的其他位置。在我们的例子中,新的运算符被重载,所有内存分配都是在预定义的内存结构上完成的。
希望我能给你一个想法。
答案 2 :(得分:1)
在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});
答案 3 :(得分:0)
当代码实际执行时,静态变量的内存仍然保留 - 您不会在堆栈上节省空间。您可能需要考虑使用向量而不是数组 - 它们更容易传递和处理。