返回C++中没有 back() 方法的容器的最后一个元素?
Returning the last element of a container that has no back() method in C++?
返回不提供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
将迭代器返回到容器最后一个元素之后的元素。此元素充当占位符;尝试访问它会导致未定义的行为。 (https://en.cppreference.com/w/cpp/container/set/end,强调我的)
另一行:
int beforeEnd = *(--set.end());
它不能保证工作。例如,请参阅 https://en.cppreference.com/w/cpp/iterator/prev,强调我的:
尽管表达式
--c.end()
经常编译,但不能保证这样做:c.end()
是一个右值表达式,并且没有迭代器要求指定保证右值的递减有效。特别是,当迭代器作为指针实现时,--c.end()
不会编译,而std::prev(c.end())
会编译。
因此,由于无法编译的原因相同,它可能会失败:
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';
}
是抓取最后一个元素以递减迭代器的唯一方法 在取消引用之前?
不,还有其他选择。
最简单的方法是使用反向迭代器(std::set::rbegin
或std::set::crbegin
),它为您提供过去std::set
结束迭代器的元素。
从 cppreference.comstd::set::rbegin and std::set::crbegin
将反向迭代器返回到反向容器的第一个元素。它对应于非反向容器的最后一个元素。如果容器为空,则返回的迭代器相等 到 rend()。
std::set<int> set = { 1,2,3,4,5 };
auto iter = set.rbegin();
const int beforeEndIter = *iter;
std::cout << "--set.end() -> " << beforeEndIter << 'n';
(更新)如果容器中的倒数第二个元素(即两个经过结束迭代器),请使用 std::next,原因与std::prev
的另一个答案中提到的相同。观看演示
std::set<int> set = {1, 2};
const bool hasElements = set.cbegin() != set.cend();
auto iter = set.rbegin();
if(hasElements && iter != set.rend()) std::cout << "--set.end() -> " << *iter << 'n';
if(hasElements && std::next(iter) != set.rend()) std::cout << "two past set.end() -> " << *std::next(iter) << 'n';
输出:
--set.end() -> 2
two past set.end() -> 1
第二个选项已在另一个答案中提到。
另一方面,取消引用结束迭代器是一种未定义的行为,您可能会期望任何结果。在您的情况下,您已经获得了容器的最后一个元素(即一个过去的结束迭代器)。
- lower_bound()返回最后一个元素
- 使用运算符 [] 引用 std::vector 上最后一个元素时出现问题<>
- Lower_bound不适用于具有 3 个元素的向量的最后一个元素
- 仅显示链表的最后一个元素
- push_back通过自行创建的对象获取最后一个元素的向量
- 使用 map.end() 访问 map 的最后一个元素
- 如何知道地图中的最后一个元素是否被删除?
- std::矢量保存 只推送最后一个元素
- 反转后不返回最后一个元素
- 如何在新数组较小时创建新数组并将旧数组的最后一个元素复制到新数组中?
- 在 QListView 中显示最后一个元素
- C++:在进行切片时对迭代器的约定,特别是对于访问最后一个元素并最终将其删除
- 遍历列表包含排除最后一个元素的内容
- 如何打印第一个和最后一个元素的和,然后打印第二个和倒数第二个元素的总和,依此类推
- C++链表最后一个元素的迭代器?
- 这种获取模板参数包中最后一个元素的方法是否有隐藏的开销?
- 使用 STL 交换堆栈 C++ 中的第一个和最后一个元素
- 数组:如何在指定索引之前显示数组的第一个和最后一个元素以及数组元素的差异?
- 你能pop_back一个向量,并且仍然使用迭代器到最后一个元素吗?
- 如何使用第一个、中间和最后一个元素的中位数正确分区?