当我们写 if(mp.find()==mp.end()) 时到底会发生什么

1 c++ iterator hashmap

我目前正在学习 hashmap,在 if 语句中使用它时,我在理解迭代器方面遇到了困难。

例如,


int main ()
{
  std::map<char,int> mymap;
  std::map<char,int>::iterator it;
  mymap['a']=50;
  mymap['b']=100;
  mymap['c']=150;
  mymap['d']=200;

  it = mymap.find('d');
  if (it == mymap.end())
    mymap.erase (it);
  if (it != mymap.end())
    mymap.erase (it);
}
    
Run Code Online (Sandbox Code Playgroud)

我能够理解第二个if 语句中发生的情况。谁能解释一下第一个if 语句到底会做什么?当我尝试删除 d 的值时,它什么也没做。有人能解释一下这两个 if 语句之间的区别吗?

Ted*_*gmo 6

std::map::erase

迭代器 pos 必须有效且可取消引用。因此,end()迭代器(有效,但不可取消引用)不能用作 pos 的值。

由于以下部分代码不符合上述规定

if (it == mymap.end())
    mymap.erase (it);
Run Code Online (Sandbox Code Playgroud)

该程序将具有未定义的行为,以防万一it == mymap.end()- 这意味着它几乎可以做任何事情,包括什么也不做或崩溃。避免像瘟疫一样的未定义行为。


另一部分是正确的做法。在使用它删除元素之前,确保它it不是迭代器。end()

if (it != mymap.end())
    mymap.erase (it);
Run Code Online (Sandbox Code Playgroud)

有人能解释一下这两个 if 语句之间的区别吗?

it = mymap.find('d');'d'在 中搜索map。如果'd'找到,它将返回一个迭代器到映射中找到该键的 'd'位置。如果'd'没有找到,则返回end()迭代器。end()所有标准容器中的迭代器(可能的例外:),basic_string甚至普通数组,都是不可取消引用的。用数组来说明:

int a[] = {7,8,9};
Run Code Online (Sandbox Code Playgroud)

内存布局:

addr   a+0 a+1 a+2 a+3
      +---+---+---+---
value | 7 | 8 | 9 | (out of bounds)
      +---+---+---+---
        ^           ^
        |           |
std::begin(a)   std::end(a)
Run Code Online (Sandbox Code Playgroud)

普通数组的迭代器end()指向最后一个元素之后的一步,取消引用它意味着您越界,从而导致未定义的行为。s与 s 类似map,只是内存布局不像普通数组那么简单。

因此,这两个语句之间的区别if在于,一个语句确保迭代器在使用它之前可以被引用erase- 而另一个语句则确保迭代器不是应该被引用(或与 一起使用)的迭代器,无论如何,erase在使用它之前erase