我见过一个类,它是一个像这样定义的类。

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来扩展这个类。

这是否安全只是因为只有一个成员并且它已在堆上分配?

有帮助吗?

解决方案

这是一个旧的C技巧,用于解决普通C中不可用长度数组的问题。是的,它也可以在C ++中工作,只要你使用合适的分配器结构(比如分配一堆原始内存)所需的大小,然后放置新的对象在那里)。只要你没有在分配的内存的末尾徘徊,它就是安全的,但它确实会让至少混淆一些内存调试器。

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

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

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

其他提示

如果iBuf是结构的最后一个成员,那么POD就可以了。非POD的问题可能是例如。编译器可以自由重新排序公共/私有/受保护成员,虚拟基类最终会在最大派生对象IIUC的末尾等等。

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

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

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

你应该确保malloc获取的内存应该是免费释放的,所以删除这样的实例:

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

也许您想使用 :: operator new()进行分配

严格来说,由于 StringChild 是从 StringBase 派生的,所以它并不安全。 C ++标准没有指定基类子对象的布局。第10条第3款:

  

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top