删除了 C 标签,因为它造成了一些困惑(它不应该从那里开始;对于在那里给您带来的任何不便,我们深表歉意。尽管 C 的回答仍然受欢迎 :)
在我所做的一些事情中,我发现需要创建具有动态大小和静态大小的对象,其中静态部分是您的基本对象成员,动态部分是数组/缓冲区直接附加到类上,保持内存连续,从而减少所需分配的数量(这些是不可重新分配的对象),并减少碎片(尽管不利的一面是,可能更难找到足够大的 block , 然而这比堆碎片更罕见 - 如果它甚至应该发生的话。这对于内存非常宝贵的嵌入式设备也很有帮助(但是我目前没有为嵌入式设备做任何事情)和事情像 std::string 需要避免,或者不能像在普通 union 的情况下那样使用。
通常我会采用的方法是(ab)使用 malloc(std::string 不是故意使用的,并且出于各种原因):
struct TextCache
{
uint_32 fFlags;
uint_16 nXpos;
uint_16 nYpos;
TextCache* pNext;
char pBuffer[0];
};
TextCache* pCache = (TextCache*)malloc(sizeof(TextCache) + (sizeof(char) * nLength));
然而,这对我来说不太合适,因为首先我想使用 new 来做这个,因此在 C++ 环境中,其次,它看起来很糟糕 :P
所以下一步是模板化的 C++ 变体:
template <const size_t nSize> struct TextCache
{
uint_32 fFlags;
uint_16 nXpos;
uint_16 nYpos;
TextCache<nSize>* pNext;
char pBuffer[nSize];
};
然而,这有一个问题,即存储指向可变大小对象的指针变得“不可能”,因此接下来的工作是:
class DynamicObject {};
template <const size_t nSize> struct TextCache : DynamicObject {...};
然而,这仍然需要转换,并且当有多个动态大小的对象派生自它时,到处都有指向 DynamicObject 的指针会变得不明确(它看起来也很糟糕,并且可能会遇到一个错误,该错误会强制空类仍然具有大小,尽管这可能是一个古老的、已灭绝的错误...)。
然后是这样的:
class DynamicObject
{
void* operator new(size_t nSize, size_t nLength)
{
return malloc(nSize + nLength);
}
};
struct TextCache : DynamicObject {...};
这看起来好多了,但是会干扰已经有 new 重载的对象(它甚至可能影响 placement new...)。
最后我想出了放置新的滥用:
inline TextCache* CreateTextCache(size_t nLength)
{
char* pNew = new char[sizeof(TextCache) + nLength];
return new(pNew) TextCache;
}
然而,出于多种原因,这可能是迄今为止最糟糕的想法。
那么有没有更好的方法来做到这一点?或者上述版本之一会更好,或者至少可以改进?这样做甚至被认为是安全和/或糟糕的编程实践吗?
正如我上面所说的,我试图避免双重分配,因为这不需要两次分配,这使得将这些东西写入(序列化)到文件中变得容易得多。 我的双重分配要求的唯一异常(exception)是它的开销基本上为零。我遇到的唯一原因是我从固定缓冲区( using this system ,我想出了)顺序分配内存,但它也是防止过度复制的特殊异常(exception)。
最佳答案
我会寻求与 DynamicObject
概念的妥协。所有不依赖于大小的东西都进入基类。
struct TextBase
{
uint_32 fFlags;
uint_16 nXpos;
uint_16 nYpos;
TextBase* pNext;
};
template <const size_t nSize> struct TextCache : public TextBase
{
char pBuffer[nSize];
};
这应该会减少所需的转换。
关于c++ - 创建动态大小的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3659946/