std::next with n > std::d istance(it, c.end())
std::next with n > std::distance(it, c.end())
我不想使用std::distance
,因为它会计算从迭代器到终点的整个距离。但是我需要确保从迭代器到最后有 N 个或更多元素。所以我正在使用下一个代码:
if (std::next(it, n) != c.end()) // c is a std::multimap
{
/// my logic
}
一切都很棒,并且与我的编译器(g++ (GCC) 4.8.3 20140911 (Red Hat 4.8.3-9)
)一起工作,但我有疑问。在文档(cpprefenece.com&&cplusplus.com)中,我找不到有关n > std::distance(it , c.end())
或任何其他特殊情况的任何信息。所以。我的代码安全吗?或者我应该写我自己的nextIfPossible
?
distance(it, c.end())
小于n
,则next(it, n)
是未定义的行为。
[C++14: 5.7/5] 如果指针操作数和结果都指向同一数组对象的元素,或者指向数组对象的最后一个元素,则计算不应产生溢出;否则,行为是未定义的。
有关详细信息,请参阅此处:非取消引用迭代器是否超过了数组未定义行为的"一个过去结束"迭代器?
您必须编写nextIfPossible
否则您的代码是未定义的。也就是说,由于我猜这是一个随机访问迭代器,您会发现在必须执行边界检查的情况下,使用索引进行基准测试比使用迭代器更快:https://stackoverflow.com/a/37299761/2642059
所以我建议甚至不要打扰迭代器或nextIfPossible
而只是使用索引并根据大小检查它。
根据标准 §24.4.4/p3 和 p6 迭代器操作 [iterator.operations](强调我的):
因此,template <class InputIterator, class Distance> constexpr void advance(InputIterator& i, Distance n);
2 要求:n 仅对双向和随机为负数 访问迭代器。
3效果:递增(或负 n 的递减) 迭代器引用 i by n。
template <class InputIterator> constexpr InputIterator next(InputIterator x, typename std::iterator_traits<InputIterator>::difference_type n = 1);
6效果:相当于:
advance(x, n); return x;
没有边界检查,因此如果输入n
大于 std::distance(it , c.end())
,则可能会导致未定义的行为。
libstd++
中RB_Tree::iterator
增量运算符的实现可确保它不会将迭代器返回到未定义的内存位置:
static _Rb_tree_node_base*
local_Rb_tree_increment(_Rb_tree_node_base* __x) throw ()
{
if (__x->_M_right != 0)
{
__x = __x->_M_right;
while (__x->_M_left != 0)
__x = __x->_M_left;
}
else
{
_Rb_tree_node_base* __y = __x->_M_parent;
while (__x == __y->_M_right)
{
__x = __y;
__y = __y->_M_parent;
}
if (__x->_M_right != __y)
__x = __y;
}
return __x;
}
但对于std::vector
来说并非如此:
#include <iostream>
#include <vector>
#include <iterator>
int main() {
std::vector<int> vec = {1,2};
auto it = vec.begin();
it = std::next(it, 5);
if (it != vec.end()) {
std::cout << "Not end..go on" << std::endl;
}
return 0;
}
这将继续打印消息。
因此,由于容器之间的行为并不相同,因此对于基于 map
的容器,您不应依赖 std::next
来实现其当前正确行为。
- 使用std::multimap迭代器创建std::list
- C++中std::resize(n)和std::shrink_to_fit之间的区别
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 如何导出包含具有"std::unique_ptr"值的"std::map"属性的
- 从持续时间构造std::chrono::system_clock::time_point
- std::具有相同基类的类的变体
- std::向量与传递值的动态数组
- 使用std::vector的OpenCL矩阵乘法
- std::map<struct,struct>::find 找不到匹配项,但是如果我循环通过 begin() 到 end(),我在那里看到匹配项
- std::condition_variable::wait()如何评估给定的谓词
- 如何获取std::result_of函数的返回类型
- std::原子加载和存储都需要吗
- 将对象移动到std::shared_ptr
- POCO::PostgreSQL:如何将std::vector支持添加到`Binder::bind`
- 为什么当我为 for(auto& it : myUnorderedMap) {... = std::move(it.second)} 时,我会得到一个 const 引用?
- 在 std::list 中,std::d istance(it.begin(), std::p rev(it.end()
- for-each 循环生成错误,但 for(it=begin()...在遍历 std::map 包含 unique_ptr 时不会
- std::map::erase(it++)是否维护一个指向映射中下一个元素的有效迭代器
- std::next with n > std::d istance(it, c.end())