在不提供 back()
成员函数(例如 std::set
)的容器中返回最后一个元素的最佳方法是什么?
由于 end()
方法返回指向容器末尾后第一个元素的迭代器,是否是获取最后一个元素以在取消引用之前递减迭代器的唯一方法?
如:
std::set<int> set = {1,2,3,4,5};
int end = *(set.end());
int beforeEnd = *(--set.end());
std::cout << "set.end() -> " << end << std::endl;
std::cout << "--set.end() -> " << beforeEnd << std::endl;
然而,这些都返回:
set.end() -> 5
--set.end() -> 5
这是获取最后一个元素的正确方法吗?为什么它们返回相同的值?
最佳答案
这个
int end = *(set.end());
正如 πάντα ῥεῖ 评论的那样, 具有未定义的行为。那是因为 std::set::end
Returns an iterator to the element following the last element of the container. This element acts as a placeholder; attempting to access it results in undefined behavior. (https://en.cppreference.com/w/cpp/container/set/end, emphasis mine)
另一行:
int beforeEnd = *(--set.end());
它不能保证工作。参见例如https://en.cppreference.com/w/cpp/iterator/prev ,强调我的:
Although the expression
--c.end()
often compiles, it is not guaranteed to do so:c.end()
is an rvalue expression, and there is no iterator requirement that specifies that decrement of an rvalue is guaranteed to work. In particular, when iterators are implemented as pointers,--c.end()
does not compile, whilestd::prev(c.end())
does.
因此它可能会因为无法编译的相同原因而失败:
int arr[4] = {1,2,3,4};
int *p = --(arr + 4); // --> error: expression is not assignable
您可以改为编写如下内容。
std::set<int> set = {1,2,3,4,5};
if ( set.begin() != set.end() )
{
auto itLast = std::prev(set.end());
std::cout << "last -> " << *itLast << '\n';
}
关于c++ - 返回在 C++ 中没有 back() 方法的容器的最后一个元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55712753/