map :: iterator会产生左值吗?

时间:2010-09-21 15:46:26

标签: c++ stl map containers

换句话说,当imap<K,V>::iterator时,请执行以下操作以提供预期的语义(即,它会修改地图):

*i = make_pair(k, v);
i->first = k;
i->second = v;

更新:前两行无效,因为operator*的返回值是(可转换为?)a pair<const K, V>。第三行怎么样?

假设对这三个人的答案,这意味着:

  • map<K,V>个元素都存储为某个地方的pair<K,V>
  • 或者有一些聪明的代理类map<K,V>::iterator::operator*返回。在这种情况下,operator->如何实施?

4 个答案:

答案 0 :(得分:4)

我试图通过标准来追踪这一点:

  • 对于map<Key,T> value_typepair<const Key,T>每23.3.1 / 2

  • map类支持双向迭代器,按照23.3.1 / 1

  • 双向迭代器满足前向迭代器的要求,符合24.1.4 / 1

  • 对于带有a value_type的转发迭代器T,表达式*a会返回 T&amp; (不是“可转换为”的类型T“,正如其他一些迭代器所做的那样)(24.1.3中的表74)

因此,要求是返回对pair的引用,而不是其他代理类型。

答案 1 :(得分:3)

地图几乎就像一对配对。是的,它的迭代器可能被实现为指向具有pair<const K,V>的节点的指针。 然而您的代码无效,因为这些值实际上属于pair<const K, V>类型,因此您无法分配给first

*我返回pair<const K, V>& 或某些行为类似的代理(无法找到标准中最后一个声明的备份)。您可以通过重载operator ->来实现此类代理。

答案 2 :(得分:1)

首先,从技术上讲,一元*运算符在这种情况下求值为左值。但是,C中的术语lvalue基本上指的是在存储(存储器)中具有位置(地址)的东西。在C ++术语中,甚至函数都是 lvalues 。所以,再次,在上面的例子中,一元*产生一个左值。如果您愿意,可以使用该左值的地址,即您可以评估&*i&i->first&i->second(假设内置的一元&

其次,由于您的原始示例涉及赋值,因此您必须实际谈论可修改的左值。你看, lvalue 的属性本身与可分配的关系很少。要使用内置赋值运算符,需要可修改的左值。从解除引用的迭代器获得的是value_type std::map。如你所知,它是一对具有const限定的第一个成员。这会自动使第一个成员不可修改,这使得整个对无法通过内置赋值运算符进行修改。正如您自己观察到的那样,该对中的第二个成员是可修改的。

因此,在这种情况下,取消引用运算符再次返回左值。这个左值作为一个整体是不可修改的,它的第一个成员也是不可修改的。它的第二个成员是可修改的左值。

至于你关于如何存储std::map元素的假设,我会说在一个典型的实现中,它们将被存储为pair<const K, V>个对象,即dereference运算符所评估的对象。通常,映射在初始化之后不需要修改该对的键部分,因此它不应该遇到任何问题,因为该对的第一个成员是const限定的。

答案 3 :(得分:1)

map<K,V>::iterator i = my_map.begin();

*i = make_pair(k, v); // invalid, you cannot assign to a pair<const K,V>&
i->first = k; // invalid cannot write to const
i->second = v; // valid