考虑以下代码示例:
#include <set>
#include <string>
using namespace std;
set<string> string_set;
void foo(const string& a)
{
pair<set<string>::iterator, bool> insert_result = string_set.insert(a);
string& val = *(insert_result.first);
val += " - inserted";
}
所以,除了正确性之外,例如不检查插入成功等等,这段代码看起来应该允许我在插入后修改字符串,但是编译器(VS2010)禁止将迭代器解除引用到非const字符串(我们是从VS2005迁移而来的,没有任何警告就挥了挥手)。
现在,我知道这应该是禁止的,因为它可能会使字符串不唯一,我很高兴它以这种方式工作,但在现实世界的情况下它不是那么明确,因为我想修改一个不参与等价测试或排序的不可变数据成员。
我想知道的是,编译器如何知道我不允许这样做,以及如何在不参考文档的情况下知道(无论如何都没有提及)?
干杯, 盖
答案 0 :(得分:24)
因为按照标准,通过修改
不允许set<>::iterator
。标准具体
允许set<>::iterator
和set<>::const_iterator
成为。{1}}
相同的类型。虽然它不要求它们是相同的
类型,它确实需要value_type
的{{1}}
是set<>::iterator
。
当然,其原因在于对...的任何修改
值可能会使const
的不变量无效。
答案 1 :(得分:3)
来自标准:
23.3.3
集合是一种关联 容器,支持唯一键 (每个密钥最多包含一个 价值)并提供快速检索 钥匙本身。班级集 支持双向迭代器。
这也来自标准:
typedef实现已定义
迭代器;
//见23.1
set :: iterator的真正实现是一个常量迭代器,以保持需求具有唯一键。否则,您可以将set中的值更改为所有相同的值。