对空向量进行 std::sort [关闭]
Posted
技术标签:
【中文标题】对空向量进行 std::sort [关闭]【英文标题】:std::sort on empty vector [closed] 【发布时间】:2014-06-18 16:28:21 【问题描述】:如果std::sort
得到一个空范围,它是否应该正常工作?
我收到此代码的分段错误 (gcc 4.8.3):
std::vector<float> f;
std::sort( f.begin() + 1, f.end() );
标准规定对于空向量 begin()
和 end()
返回相同的值。所以我希望sort
在上述情况下什么都不做,因为它应该得到一个空范围:begin()+1
应该大于end()
。
这个空范围排序没有问题:
std::sort( f.begin(), f.end() );
【问题讨论】:
那么f.begin() + 1
呢?那岂不是越界了?
@juanchopanza 这是一些价值,重要的是begin() + 1
是> end()
。
这是一个无效迭代器的值。它不是>
或<
而不是end()
。它只是无效的。
@user2052436,这是未定义的行为。在一个空范围内,begin() == end()
。
【参考方案1】:
std::sort
期望[begin, end)
是一个有效范围,这样如果你不断增加begin
,你最终会到达end
。在您的情况下,begin()+1
超出了end()
,因此std::sort
无法知道它正在查看范围的末尾。
std::sort
接受迭代器,而不是指针。正因为如此,它无法运行begin < end
检查:如果您为两个迭代器传递了rbegin()
和rend()
,这将失败。
如果您想对不包括初始元素的std::vector
的一部分进行排序,则需要确保容器不为空。否则,begin()+1
将产生无效的迭代器。
注意:虽然从技术上讲,当您在空容器上执行 begin()+1
时会发生未定义的行为,但您的情况下的崩溃几乎肯定来自 std::sort
内部的取消引用。另请注意,如果您有兼容 C++11 的编译器,则使用 std::next(v.begin(), 1)
比使用 v.begin() + 1
更可取。
【讨论】:
你没有进入 std::sort,一切都已经结束了。 好的,现在你也指出实际的错误,我推翻了我的投票。【参考方案2】:输入迭代器的增量有一个先决条件,即迭代器必须是可解引用。对于空向量,v.begin()
是不可取消引用的,因此尝试执行 v.begin() + 1
(它又以增量定义)是未定义的行为。
此外,std::sort(begin, end)
要求 [begin, end)
是一个有效范围,标准规定 (§24.2.1 [iterator.requirements.general]/p7)
当且仅当
j
可以从i
到达时,范围[i,j)
才有效。将库中的函数应用于无效范围的结果未定义。
对于大多数随机访问迭代器(唯一定义了<
和>
的迭代器类型),如果a > b
则a
无法从b
访问,因此[a, b)
确实not 表示空范围 - 它根本不表示有效范围。
【讨论】:
@Deduplicator ...这是第一段? @Deduplicator UB 并不总是直接显示。在这里,段错误可能源自it != end
,因此取消引用begin + 1
(指向无效内存,是的)将会发生,所以繁荣。是的,从技术上讲,该程序在v.begin() + 1
展示了 UB,但其余部分也很重要。
@Deduplicator v.begin() + 1
是未定义行为的原因恰恰是因为v.begin()
是不可取消引用的,并且您违反了先决条件。【参考方案3】:
f.begin()+1
超出范围,这就是分段错误的原因。
使用f.begin()
作为数组的开头。这样可以安全使用。
【讨论】:
好的,所以要排除第一个元素,我需要在调用sort
之前检查size() > 0
。以上是关于对空向量进行 std::sort [关闭]的主要内容,如果未能解决你的问题,请参考以下文章