【发布时间】:2015-03-21 12:59:42
【问题描述】:
考虑以下示例:
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. 在 Init 中,将 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 集合时,非 const 参数必须变为 NULL,最终尝试修改集合会崩溃(尝试取消引用 NULL 指针),这很好(安全)。我们有额外的存储费用。这很尴尬,取同一个集合的两个指针。
我也有点担心编译器在同一上下文中看到两个指针,这意味着如果通过可写指针修改集合,编译器必须意识到只读指针可能指向同一个对象并且尽管有 const 限定符,它仍需要重新加载。这安全吗?
你会选择哪一个,为什么? 你知道解决这个问题的更好方法吗?
【问题讨论】:
-
为什么 SomeFunction have 需要一个指向 const 的指针?只需让用户传递一个非 const 对象即可。
-
@reader 在无数情况下,函数“保证”它们不会修改对象。它有利于优化并且在多线程代码中是无价的。
标签: c struct constants qualifiers