c++ - 返回在 C++ 中没有 back() 方法的容器的最后一个元素?

标签 c++ algorithm c++11 iterator containers

在不提供 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, while std::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/

相关文章:

c++ - 处理cpp中的对象时出错

c++ - 在您配置的INTEL C++编译器(Linux)的搜索路径中找不到可执行文件

c++ - 通用数据库管理器(包装器)

c++ - 尝试使用 {} 和 std::make_pair() 交换两个变量时的不同行为

python - python 中的组合数(考虑传递性)

php - 在页面拆分输出中合并来自不同表的搜索结果

java - 将树(非二进制)转换为路径列表

c++ - 为什么 `std::move` 命名为 `std::move` ?

c++ - 为什么允许 int 和 const int 的不同转换函数?

c++ - 如何将 OpenCV 的 Mat 结构的部分图像矩阵加载到我自己的 3x3 数组中?