2009-01-09 86 views
1

我见过一类是这样定义一个类..可变大小的类 - C++

class StringChild : public StringBase 
    { 
public: 
    //some non-virtual functions 
    static StringChild* CreateMe(int size); 
private: 
    unsigned char iBuf[1]; 
    }; 

静态工厂函数具有以下实现..

return new(malloc(__builtin_offsetof(StringChild ,iBuf[size]))) StringChild(); 

所以据我所知,这个函数使用placement new来扩展这个类。

这是安全的只是因为只有1个成员,它被分配在堆上?

回答

5

就这么用作使用合适的分配器构建体(如分配一束原始存储器的解决纯C.是的,它也可以用C可变长度数组++非可用性只要一个旧的C特技所需的大小,然后放置新的对象在那里)。只要你不会在分配的内存末尾漫游,它是安全的,但它至少会混淆至少一些内存调试器。

使用这种技术时必须要做的一件事就是可变长度数组是对象布局中的最后一个元素,否则您将遍历其他内部变量。

但是我对工厂函数的实现有点怀疑 - 我认为'size'参数实际上是所需的数组大小?另外,不要忘记,你必须使用'free'而不是'delete'来释放上面的内存,尽管后者在大多数情况下都可以工作。

除非有一个令人信服的理由说明为什么要这样管理内存,否则我只需用std :: vector来替换数组。

+0

我是在假设你无法理会成员的顺序的情况下,我的问题是这只是安全的,因为只有一个成员。 – Dynite 2009-01-09 11:53:33

3

这应该是确定的POD提供iBuf是结构的最后一个成员。非POD的问题可能是,例如。编译器可以自由地对公共/私有/受保护成员进行重新排序,虚拟基类最终在最衍生对象IIUC的末尾等。

你的结构是非POD(它有一个基类),所以我不会' t推荐它。

另外,如果你创建实例这样

return new(malloc(__builtin_offsetof(StringChild ,iBuf[size]))) StringChild(); 

你应该确保通过的malloc获得的内存应使用自由释放,因此删除您的实例是这样的:

obj->~StringChild(); 
free(obj); 

也许你'd喜欢用::operator new()进行分配

0

严格来说,因为StringChild是从StringBase派生的,所以它不是sa FE。 C++标准没有指定基类子对象的布局。条款10第3段:

未指定基类子对象在最大派生对象(1.8)中的分配顺序。

如果StringChild是POD结构,那么这样的技术是安全的。