代码之家  ›  专栏  ›  技术社区  ›  Alexandre C.

map::iterator是否生成lvalues?

  •  3
  • Alexandre C.  · 技术社区  · 14 年前

    换句话说,当 i 是一个 map<K,V>::iterator ,请执行以下操作以提供预期的语义(即它修改映射):

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

    ?

    更新: 前两行无效,因为 operator* (可转换为?)一 pair<const K, V> . 第三条线怎么样?

    假设 回答这三个问题,这意味着:

    • 要么 map<K,V> 元素存储为 pair<K,V> 在某个地方,
    • 或者有一些聪明的代理类 map<K,V>::iterator::operator* 返回。在这种情况下,如何 operator-> 是否实施?
    4 回复  |  直到 14 年前
        1
  •  4
  •   Cubbi    14 年前

    我试图通过标准来追踪:

    • 对于一个 map<Key,T> 这个 value_type pair<const Key,T> 根据23.3.1/2

    • map类支持双向迭代器,根据23.3.1/1

    • 根据24.1.4/1,双向迭代器满足正向迭代器的要求。

    • 对于正向迭代器 a 具有 值类型 T ,表达式 *a 退货 T&P; (不是像其他迭代器那样的“可转换为T”类型)(24.1.3中的表74)

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

        2
  •  3
  •   Yakov Galka    14 年前

    地图几乎像一组对。是的,它的迭代器可能实现为指向具有 pair<const K,V> . 然而 您的代码无效,因为值实际上是类型 pair<const K, V> 所以你不能分配给 first .

    *我回来了 pair<const K, V>& 或一些类似于此类型的代理 (在标准中找不到上次索赔的备份)。您可以通过重载来实现这些代理 operator -> .

        3
  •  1
  •   sbi    14 年前

    首先,从技术上讲,一元 * 在这种情况下,运算符计算为左值。然而,C中的lvalue这个术语基本上是指在存储(内存)中具有位置(地址)的东西。在C++术语中,偶函数也是 吕瓦勒斯 . 所以,在你的例子中,在一元以上 * 产生一个左值。如果您希望这样做,您可以获取该左值的地址,也就是说,您可以评估 &*i , &i->first &i->second (假设内置一元 & )。

    第二,由于您最初的示例涉及到赋值,所以您必须实际谈论 可修改值 . 你看,存在的属性 左值 它本身与可分配性几乎没有关系。要使用内置的赋值运算符,需要 可修改的左值 . 从未引用的迭代器中得到的是 value_type 属于 std::map . 它是一对具有const限定的第一个成员,如您所知。这将自动使第一个成员不可修改,并使整个对不可由内置的赋值运算符修改。正如您已经观察到的那样,对的第二个成员是可修改的。

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

    至于你关于 STD::地图 在典型的实现中,它们将存储为 pair<const K, V> 对象,即解引用运算符的计算结果。通常,映射在初始化后不需要修改对的键部分,因此它不应该遇到任何问题,因为对的第一个成员是常量限定的。

        4
  •  1
  •   sbi    14 年前
    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