插入后的 std::list 结束迭代器

发布于 2025-01-16 05:58:20 字数 842 浏览 0 评论 0原文

在 std::list 中,容器内的插入不应使迭代器无效,但它是如何实现的呢?例如,我有一个列表并插入一个值:

std::list<int> list;
list.push_back(12);

然后我得到结束迭代器:

auto end = list.end();
auto it = --end;

现在结束应该指向插入的元素。当我保留结束迭代器并进行另一次插入时会发生什么? --end 仍会指向 12 或新插入的值吗?

编辑1:

我用以下程序对此进行了测试:

#include <iostream>
#include <string>
#include <list>

int main()
{
  std::list<int> list;
  list.push_back(12);
  auto end = list.end();
  auto it = std::prev(end);
  
  std::cout << *it << std::endl;
  list.push_back(13);
  it = std::prev(end);
  std::cout << *it << std::endl;
  it = std::prev(end);
  std::cout << *it << std::endl;
}

这给了我 12 13 13 作为结果,我不明白,因为我在第二次插入后没有编辑结束迭代器。这意味着容器可以访问push_back内部的迭代器内部?

In std::list an insertion inside the container should not invalidate an iterator but how is that implemented? For example I have a list and insert one value:

std::list<int> list;
list.push_back(12);

Then I get the end iterator:

auto end = list.end();
auto it = --end;

Now end should point to the inserted element. What happens when I keep the end iterator and do another insertion? Will --end still point to 12 or to the new inserted value?

Edit1:

I tested this with the following program:

#include <iostream>
#include <string>
#include <list>

int main()
{
  std::list<int> list;
  list.push_back(12);
  auto end = list.end();
  auto it = std::prev(end);
  
  std::cout << *it << std::endl;
  list.push_back(13);
  it = std::prev(end);
  std::cout << *it << std::endl;
  it = std::prev(end);
  std::cout << *it << std::endl;
}

This gives me 12 13 13 as result which I don't understand because I did not edit the end iterator after the second insertion. This means the container has access to the iterator internals inside push_back?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

双手揣兜 2025-01-23 05:58:20

结束迭代器不会被push_back失效*,这意味着它将保留指向末尾。 (在这种情况下,您可以将其视为始终结束的哨兵节点的迭代器)


std::list<int> list;
list.push_back(12);
auto end = list.end();

// one before the end
auto it = std::prev(end);
std::cout << *it << std::endl;
list.push_back(13);

// one before the end (now with 2 element)
it = std::prev(end);
std::cout << *it << std::endl;

// std::prev doesn't change `end` so it's the same as above
it = std::prev(end);
std::cout << *it << std::endl;


*另一方面 std::vector 确实有一些使结束迭代器无效的操作

The end iterator is not invalidated by push_back*, which means it would keep point to the end. (in this case you can think it as a iterator to a sentinel node that's always the end)


std::list<int> list;
list.push_back(12);
auto end = list.end();

// one before the end
auto it = std::prev(end);
std::cout << *it << std::endl;
list.push_back(13);

// one before the end (now with 2 element)
it = std::prev(end);
std::cout << *it << std::endl;

// std::prev doesn't change `end` so it's the same as above
it = std::prev(end);
std::cout << *it << std::endl;


*on the other hand std::vector does have some operation that invalidate end iterator

宣告ˉ结束 2025-01-23 05:58:20

当我保留结束迭代器并进行另一次插入时会发生什么?

--end 修改迭代器,使其指向第二个元素插入前后的12。

如果保留结束迭代器而不对其进行修改,它仍然是第二次插入之前和之后经过最后一个元素的迭代器。

--end 仍会指向 12 或新插入的值吗?

--end 第二次将是 UB,因为在第一次递减之后它指向第一个元素。

但如果您没有修改结束迭代器,那么第一个 --end 将生成一个指向最后一个元素的迭代器。

例子:

std::list<int> list;
list.push_back(12);
auto end1 = list.end();
auto end2 = list.end();
auto it1 = --end1;    // refers to to 12
list.push_back(13);
auto it2 = end1;      // refers to to 12
// auto it3 = --end1; // UB
auto it4 = --end2;    // refers to 13

What happens when I keep the end iterator and do another insertion?

--end modifies the iterator, so it points to the 12 before and after the insertion of the second element.

If you had kept the end iterator without modifying it, it would still be the iterator to one past the last element before and after the second insertion.

Will --end still point to 12 or to the new inserted value?

--end second time would be UB because after the first decrement it points to the first element.

But if you had not modified the end iterator, then the first --end would produce an iterator to the last element.

Example:

std::list<int> list;
list.push_back(12);
auto end1 = list.end();
auto end2 = list.end();
auto it1 = --end1;    // refers to to 12
list.push_back(13);
auto it2 = end1;      // refers to to 12
// auto it3 = --end1; // UB
auto it4 = --end2;    // refers to 13
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文