问题描述
我正在编写一个具有结构的 API,例如
struct datast{
int a;
int *items;
size_t numitems;
};
我提供了释放此类结构内容的函数(以类似于 C++ 析构函数的方式)。未提供构造函数,因为我强制要求对它们进行零初始化(.items
字段在初始化时必须是 NULL
指针,这使其适用于以后的 realloc()
和 {{1 }}).
不过,我提供了一个 free()
函数,它 additem()
为 realloc()
并相应地增加 .items
。
但是,由于这些结构体很小,我想鼓励使用指定的初始化器和复合字面量,以便用户可以在可能的情况下方便地使用单行创建这些对象,而无需手动调用 {{1} }.
但是,如果您使用指定的初始值设定项初始化这些结构(或从复合文字分配给它们),.numitems
字段将具有自动存储空间而不是分配的存储空间。因此,如果您稍后将此结构传递给“释放”函数/析构函数,您将使用非法指针(指向自动存储)调用 additem()
。
是的,我知道措辞可能是“不要为没有调用 .items
的对象调用析构函数”...但这看起来真的很笨拙,而且设计很糟糕。
不知何故,这就像我必须决定所有这些对象应该有自动存储还是分配存储,而不给用户提供这两种可能性。
你遇到过这样的场景吗?有没有什么设计可以为自动存储和分配存储提供干净优雅的界面?
解决方法
添加布尔成员 items_allocated
。您强制要求的零初始化将使 false
。然后 additem()
会将它设置为 true
:
struct datast
{
int a;
int *items;
bool items_allocated ;
size_t numitems;
} ;
那么你的析构函数可以是这样的:
if( d->items_allocated )
{
free( d->items ) ;
d->items = NULL ;
}
d->numitems = 0 ;
...