为什么 std::end() 返回的值会随着容器的变化而变化,而 std::begin() 不会?

Ale*_*ter 0 c++ iterator stl

我有一个std::list我正在插入项目的std::unordered_map地方,我有一个地方我想将迭代器存储到插入到的元素中std::list(我正在实现一个 LRU 缓存)。下面的代码没有给我我期望的输出:

#include <list>
#include <unordered_map>
#include <iostream>


int main()
{
    std::list<int> l;
    std::unordered_map<int, std::list<int>::iterator> listItems;
    
    for (int i = 0; i < 5; i++)
    {
        l.push_back(i);
        listItems[i] = std::end(l);
    }
        

    for (int i = 0; i < 5; i++)
        std::cout << *(listItems[i]) << " ";
    std::cout << std::endl;

}
Run Code Online (Sandbox Code Playgroud)

这里的输出是5 5 5 5 5- 我想要/期望的输出是0 1 2 3 4. 我会猜到这段代码会std::end返回一个迭代器到列表的最后一个元素,它被复制到 listItems[i] 中,但这显然不是正在发生的事情。我很困惑为什么将项目添加到列表会影响先前调用的结果std::end

但是,如果我将第一个循环更改为

for (int i = 0; i < 5; i++)
{
    l.push_front(i);
    listItems[i] = std::begin(l);
}
Run Code Online (Sandbox Code Playgroud)

我得到了我期望的输出 - 0 1 2 3 4。那么这里push_frontand push_back, and std::beginand之间有什么区别std::end

pre*_*uin 5

为了得到最后一个元素的迭代器,它可以通过以下方式实现:std::prev(std::end(l))。您的代码存储了结束迭代器并取消引用它,它是 UB。

DOCstd::list::end

返回容器最后一个元素之后的元素的迭代器,该元素充当占位符;尝试访问它会导致未定义的行为。

对于std::begin,我们将迭代器获取到容器的第一个元素,可以安全地引用它并获取相应的元素。

#include <iostream>
#include <list>
#include <unordered_map>

int main() {
  std::list<int> l;
  std::unordered_map<int, std::list<int>::iterator> listItems;

  for (int i = 0; i < 5; i++) {
    l.push_back(i);
    listItems[i] = std::prev(std::end(l));
  }

  for (int i = 0; i < 5; i++) std::cout << *(listItems[i]) << " ";
  std::cout << std::endl;
}

Run Code Online (Sandbox Code Playgroud)

在线演示

  • @ChrisUzdavinis `back()` 给你一个元素而不是迭代器,这是 OP 想要的。 (2认同)