STL 中使用的 Comp 比较器是不是需要从不更改 STL 中的比较对象?

Posted

技术标签:

【中文标题】STL 中使用的 Comp 比较器是不是需要从不更改 STL 中的比较对象?【英文标题】:Is Comp comparator used in STL required to never change compared objects in STL?STL 中使用的 Comp 比较器是否需要从不更改 STL 中的比较对象? 【发布时间】:2018-02-09 12:29:40 【问题描述】:

我正在检查使用 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 的复制构造函数采用非常量引用。我一直在寻找规定这种行为的标准规则,但我能找到的只是:

[alg.sorting#2]比较是一个函数对象类型。 应用于比较类型对象的函数调用操作的返回值,当上下文转换为布尔值时,如果调用的第一个参数小于第二个参数,则返回 true,否则返回 false。 比较 comp 始终用于假设排序关系的算法。 假设 comp 不会通过取消引用的迭代器应用任何非常量函数。

但这至少还不够,因为按值获取两个 std::auto_ptr 的比较器不会“通过取消引用的迭代器应用任何非常量函数”——比较器本身不应用复制构造函数。 此外,同样的问题也适用于Compare 的超类——在关于BinaryPredicate 的[algorithms.requirements#7] 段落中,我们可以读到几乎相同的句子

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

【问题讨论】:

相关:wg21.link/LWG3031 【参考方案1】:

这基本上是LWG 3031。

您的比较对象没有违反Compare 应该如何表现的任何规定的先决条件,这是一个标准缺陷。您没有在对象上调用任何非const 操作,而是在调用非const 复制构造函数。这并没有真正涵盖。


然而,这个特殊的例子 未定义的行为有一个不同的原因:你的比较,由于它破坏了它的所有元素,将不能成为一个严格的弱顺序 - 这与 @987654322 相冲突@。

【讨论】:

我不完全相信:这样的比较器,如果“合理”,仍然有效。当然,它会修改带下划线的集合,但是对于给定的两个 auto_ptr 值,它会返回规范所要求的值。 @MichałŁoś 你能举一个比return false;更复杂的“合理”比较器的例子吗? 实际上 - 你所描述的足够合理:D,但你去吧:coliru.stacked-crooked.com/a/ace61f082d999a0a - 请注意,我指出传递给比较的值而不是对象身份。 @MichałŁoś 我不知道您是否可以称其为有效的严格弱命令。因为如果你有auto_ptr&lt;int&gt; a(new int(1)), b(new int(2)), c(new int(3));,你就会有compare(a,b)compare(b,c)b现在是空的),然后是!compare(a,c) 我完全同意这一点,但标准中使用的表示法的意图不是处理“a”和“b”值而不是实际对象吗?例如:eel.is/c++draft/alg.sorting#4.1。至少我是这么理解的。

以上是关于STL 中使用的 Comp 比较器是不是需要从不更改 STL 中的比较对象?的主要内容,如果未能解决你的问题,请参考以下文章

vector中sort用法到自定义比较函数comp

STL进阶--成员函数 vs 算法

从最简单的vector中sort用法到自定义比较函数comp后对结构体排序的sort算法

STL---heap概述及用法

STL系列之四 heap 堆

常用STL使用指北