--list.begin() == list.end() 吗?

Hi *_* SO 0 c++ iteration iterator stdlist language-lawyer

标准是否保证

--list.begin() == list.end()

总是成立并且它实际上是一个有效的操作?(list是 的一个实例std::list)。

至少 MSVC 2019 似乎就是这种情况。

例如,这在以下情况下会很有用:

for ( auto i = list.begin(); i != list.end(); ++i )
{
  ...
  list.erase(i--);
  ...
}
Run Code Online (Sandbox Code Playgroud)

,即在迭代时删除元素时,因为i可能是列表的开头。这也需要++list.end() == list.begin()持有;那个怎么样?

eer*_*ika 8

标准是否保证

--list.begin() == list.end()
Run Code Online (Sandbox Code Playgroud)

不,标准不保证 for std::list(也不能假设给定双向迭代器)。事实上, 的行为--list.begin()是未定义的。

这也需要 ++list.end() == list.begin() 来保持;那个怎么样?

也不能保证,并且++list.end()具有未定义的行为。


[语言律师]的标准报价:

[双向.迭代器]

Expression | Operational   | Assertion/note
           | semantics     | pre-/post-condition
---------------------------------------------------------
--r        |               | Preconditions:
           |               |  there exists s such that r == ++s.
---------------------------------------------------------
r--        | { X tmp = r;  |
           | --r;          |
           | return tmp; } |
Run Code Online (Sandbox Code Playgroud)

[输入.迭代器]

Expression | Operational   | Assertion/note
           | semantics     | pre-/post-condition
---------------------------------------------------------
++r        |               | Preconditions:
           |               |  r is dereferenceable.
Run Code Online (Sandbox Code Playgroud)

问题是不满足先决条件。


我对写具体例子的建议。这略有不同,my_function它将在元素从列表中实际删除之前调用:

list.remove_if([](int n) {
    if ( X + Y == W )
    {
        my_function( Y );
        return X || Y && Z;
    }
    return true;
});
Run Code Online (Sandbox Code Playgroud)

如果需要确切的行为,那么您可以使用以下不太漂亮的方法:

for (auto it = list.begin(), last = list.end(); it != last;)
{
    auto next = it;
    ++next;
    
    if ( X + Y == W )
    {
        if ( X || Y && Z )
        {
            list.erase( it );
        }
        my_function( Y );
    }
    else
    {
        list.erase( it );
    }
    
    it = next;
}
Run Code Online (Sandbox Code Playgroud)