我在嵌入式C ++项目中工作,我计划尽可能多地静态分配内存。所以,我正在编写一组函数来覆盖所有类和全局new / delete的新/删除。
这是一个天真的实现:
class MyClass
{
int x;
float y;
double z;
static MyClass m_preAllocatedObjects[100]; //Solution 1
static char m_preAllocatedMemory[100 * sizeof(MyClass)]; //Solution 2
static char* getPreAllocatedMemory() // Solution 3
{
static char localStaticMemory[100 * sizeof(MyClass)];
return localStaticMemory;
}
static void* operator new(size_t s){
void* p; /*fill p from the pre-allocated memory or object*/;
return p;
}
};
解决方案1 :仅适用于具有默认构造函数的对象。
解决方案2 :它会出现编译错误use of undefined type 'MyClass'
;和 这就是我要问的问题 。
解决方案3 :此解决方案正常运行。
问题是:
为什么我可以创建MyClass的静态成员,而我却无法获得sizeof(MyClass)?
答案 0 :(得分:3)
虽然我无法获得sizeof(MyClass)?
原因是MyClass
在类定义的结束}
之前没有完全定义,来自c ++ 11标准的 9 Classes 部分(草案n3337) ):
在看到类名后立即将类名插入到作用域中。 类名也插入到类本身的范围内;这被称为注入类名。 出于访问检查的目的,inject-class-name被视为公共成员名称。一个 class-specifier通常称为类定义。 关闭后会考虑定义一个类 已经看到它的类说明符的大括号,即使它的成员函数一般尚未定义。 可选的attribute-specifier-seq属于该类; attribute-specifier-seq中的属性是 之后,只要它被命名,就会考虑该类的属性。
和sizeof
只能应用于完整类型,部分 5.3.3 Sizeof :
sizeof运算符产生其操作数的对象表示中的字节数。操作数是 表达式,它是未评估的操作数(第5条)或带括号的type-id。 sizeof 运算符不应该应用于具有功能或不完整类型的表达式到枚举 在声明所有枚举数之前,其基础类型未修复的类型为括号 此类型的名称,或指定位字段的左值。 ...
要更正,请在类定义之外定义数组的大小:
class MyClass
{
static char m_preAllocatedMemory[];
};
char MyClass::m_preAllocatedMemory[100 * sizeof(MyClass)];
答案 1 :(得分:3)
要“知道”编译器需要知道整个类的MyClass
的大小。当你向前声明static MyClass m_preAllocatedObjects[100];
时你实际上没有定义变量 - 要实际获得变量,你必须这样做:
MyClass MyClasss::m_preAllocatedObjects[100];
.cpp文件中的某个地方。这是对象的内存被“放置”在数据段中的块。因此,编译器在声明变量时不必知道MyClass
的实际大小。但是,它确实需要知道评估100 * sizeof(MyClass)
的大小。
答案 2 :(得分:1)
你必须分两步完成:
以下是代码:
class MyClass
{
int x;
...
static char m_preAllocatedMemory[];
};
char MyClass::m_preAllocatedMemory[100 * sizeof(MyClass)];