我正在检查使用std::auto_ptr
的旧弃用代码,我想知道这是否是不确定的行为:
std::vector<std::auto_ptr<int>> v;
//populate v with elements...
std::sort(v.begin(), v.end(), [](auto a, auto b) {/* some reasonable "less" comparison */});
现在,这种比较器当然会清空集合,因为 std::auto_ptr
的复制构造函数获取非const参考。我一直在寻找标准规则,以规定这种行为,但我所能找到的只是:
[alg.sorting#2] 比较是函数对象类型。 将函数调用操作的返回值应用于类型对象,如果上下文转换为bool,则如果调用的第一个参数小于第二个,则会产生true,否则为false。 比较Comp在整个算法中都使用订购关系。 假定Comp不会通过Dereced Iterator应用任何非恒定功能。
但这至少还不够,因为按值进行两个std :: auto_ptr的比较器不会"通过删除的迭代器应用任何非恒定函数" - 比较器本身不会应用复制构造函数。此外,同一问题适用于Compare
的超类 - 在[algorithms.s.requirtement#7]有关BinaryPredicate
的段落,我们可以阅读几乎相同的句子:
binary_pred不得通过删除的迭代器应用任何非恒定功能。
这意味着如果存在问题,将传播到许多其他算法。
我的问题是:是比较器,它按值计数为std::auto_ptr
参数,违反了std::sort
的要求,将其调用为未定义的行为,或者此代码很好,只是错误地工作;(?或者,也许这是C 标准库规范中的问题?
阅读更多:
- http://eel.is/c draft/alg.sorting#2.sentence-4
- http://eel.is/c draft/algorithms.requirements#7.Sentence-4
- http://www.eel.is/c draft/sort
- http://en.cppreference.com/w/cpp/algorithm/sort
- http://en.cppreference.com/w/cpp/concept/compare
这基本上是LWG 3031。
您的比较对象不会违反Compare
应如何行为的任何既定前提,这是标准缺陷。您不会在对象上调用任何非const
操作,而是调用非const
复制构造函数。这并没有真正覆盖。
然而,这个特殊的例子是不确定的行为,原因是不同的原因:由于它破坏了其所有元素,您的比较将无法成为一个严格的弱点 - 它的运行.sorting]/3。