擦除 std::list::iterator 不会使迭代器无效并销毁对象吗?

发布于 2024-10-21 04:28:20 字数 274 浏览 1 评论 0原文

为什么下面打印2

list<int> l;
l.push_back( 1 );
l.push_back( 2 );
l.push_back( 3 );
list<int>::iterator i = l.begin();
i++;
l.erase( i );
cout << *i;

我知道 erase 返回什么,但我想知道为什么这样可以?或者它是未定义的,还是取决于编译器?

Why does the following print 2?

list<int> l;
l.push_back( 1 );
l.push_back( 2 );
l.push_back( 3 );
list<int>::iterator i = l.begin();
i++;
l.erase( i );
cout << *i;

I know what erase returns, but I wonder why this is OK? Or is it undefined, or does it depend on the compiler?

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

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

发布评论

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

评论(5

丶视觉 2024-10-28 04:28:21

是的,这是未定义的行为。您正在取消引用一种野指针。 erase 后不应使用 i 的值。

是的,擦除破坏指向的对象。然而,对于 POD 类型,销毁不会执行任何操作。

erase 不会为被擦除的迭代器分配任何特殊的“null”值,迭代器只是不再有效。

Yes, it's undefined behaviour. You are dereferencing a kind of wild pointer. You shouldn't use the value of i after erase.

And yes, erase destructs the object pointed to. However, for POD types destruction doesn't do anything.

erase doesn't assign any special "null" value to the iterator being erased, the iterator is just not valid any more.

无法回应 2024-10-28 04:28:21

“销毁”一个对象意味着它的内存被回收并且它的内容可能会被改变(主要是如果手写的析构函数这样做,并且可能是由于将与空闲内存相关的东西存储在适当的位置)。 list::erase 返回一个新的迭代器,您应该使用它来代替作为参数传递的迭代器(我很想使 i = l.erase(i); 成为一种习惯)。

破坏绝不意味着记忆被扫除、消灭。 从 CPU 的角度来看,在大多数情况下,以前的有效位置仍然有效(即它可以获取值),但不能依赖,因为其他操作可能会在任何时间出于任何目的回收该位置时间。

恕我直言,您不太可能看到 *i 抛出段错误——尽管这可能发生在使用指针的更复杂类型中,但您可能会看到它具有新值。

其他集合可能具有比列表更可预见的行为。 IIrc,向量会压缩存储区域,因此在极少数情况下,只有通过进一步取消引用 i 才能看到先前的值。

"destroying" an object means its memory is reclaimed and its content might be altered (mainly if the hand-written destructor do so, and possibly as a result of storing free-memory-related stuff in place). list::erase returns you a new iterator that you should use instead of the one that was passed as argument (I'd be tempted to make i = l.erase(i); an habbit).

In no way do destruction imply that memory is swept, wiped out. Previously valid location are still valid in most cases from the CPU's point of view (ie. it can fetch values), but can't be relied on because other operation may recycle that location for any purpose at any time.

You're unlikely to see *i throwing a segfault, imho -- although that might happen with more complex types that use pointers, but you might see it having new values.

Other collections might have a more previsible behaviour than list. IIrc, a vector would compact the storage area so the previous value would only be seen by further dereferencing i in rare cases.

烟─花易冷 2024-10-28 04:28:21

看起来迭代器仍然指向这个内存....
如果您要向此块写入一些内容,
也许下次*我会抛出分段错误..

但对猜测表示抱歉

Seems like iterator still points to this memory....
If you would write something to this block,
maybe next time *i would throw segmentation fault..

sorry for speculation though

挽手叙旧 2024-10-28 04:28:21

由于您正在处理链接列表,因此列表的元素不需要在内存中彼此位于“后面”。如果您对向量尝试相同的操作,您可能(因为行为未定义)

cout << *i

会被打印为 2。

但是,这不是一种非常安全的编程方式。因此,一旦删除迭代器,请确保不再使用它,除非您使用 begin() 或 end() 等再次初始化它。

Since you are dealing with a linked list, the elements of the list need not to be right "behind" each other in memory. If you would try the same thing with a vector, you would likely (since the behavior is undefined) experience

cout << *i

to be printed as 2.

However, this is not a very safe way of programming. So once you erase an iterator make sure not to use it again, unless you initialize it again with begin() or end() etc.

空气里的味道 2024-10-28 04:28:21

尝试使用正确的选项和良好的编译器来编译代码,
然后运行它。 (对于 VC++,/D_DEBUG /EHs /MDd 似乎是
充足的。使用 g++,<代码>-D_GLIBCXX_CONCEPT_CHECKS -D_GLIBCXX_DEBUG
至少是-D_GLIBCXX_DEBUG_PEDATIC。两个编译器都需要更多
一般选项。)它应该崩溃。 (我试过的时候确实如此。)

Try compiling your code with the correct options, with a good compiler,
then running it. (With VC++, /D_DEBUG /EHs /MDd seems to be
sufficient. With g++, -D_GLIBCXX_CONCEPT_CHECKS -D_GLIBCXX_DEBUG
-D_GLIBCXX_DEBUG_PEDANTIC
, at least. Both compilers need even more
options in general.) It should crash. (It does when I tried it.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文