考虑以下示例:
typedef struct Collection
{
...
} Collection;
typedef struct Iterator
{
Collection* collection;
} Iterator;
Iterator 是提供集合修改功能,因此它保存非常量集合的地址。然而,它也提供了非修改函数,这些函数与 const 集合一起使用是完全合法的。
void InitIterator(Iterator* iter, Collection* coll)
{
iter->collection = coll;
}
void SomeFunction(const Collection* coll)
{
// we want to use just non-modifying functions here, as the Collection is const
Iterator iter;
InitIterator(&iter, coll); // warning, call removes const qualifier
}
我正在寻找C中的解决方案。我确实看到了一些选择:
1.在初始化时,将 Collection 转换为非常量。这可能不是未定义的行为,因为对象最终不应被修改。但它令人毛骨悚然,因为有一个 const 对象,这样做是自找麻烦。Iterator 将成为一种广泛使用的通用机制,用于处理集合。当一个人要修改一个 const 集合时没有编译器警告真的很糟糕。
2.两种迭代器类型,一种是带有 const Collection* 成员的只读版本。这使使用复杂化,可能需要复制某些功能,可能由于翻译步骤而降低效率。我真的不想使 API 复杂化,并且有两个不同的结构以及两组函数。
3.具有两个指针的迭代器,而 Init 采用两个集合指针。
typedef struct Iterator
{
const Collection* collectionReadable; // use this when reading
Collection* collectionWritable; // use this when writing
} Iterator;
当有一个 const 集合时,非常量参数必须变为 NULL 并且最终尝试修改集合会崩溃(尝试取消引用 NULL 指针),这很好(安全)。我们有额外的存储费用。这很尴尬,取同一个集合的两个指针。
我也有点担心编译器在同一上下文中看到两个指针,这意味着如果通过可写指针修改了 Collection,编译器必须意识到只读指针可能指向同一个对象,它需要尽管有 const 限定符,但仍会重新加载。这安全吗?
你会选择哪一个,为什么?你知道解决这个问题的更好方法吗?