首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >std::is_sorted的怪异行为

std::is_sorted的怪异行为
EN

Stack Overflow用户
提问于 2019-06-20 14:12:33
回答 2查看 467关注 0票数 2

我正在c++中学习断言,我偶然发现了std::is_sorted的奇怪行为。

给定比较器(C)和未排序向量(V)的std::字符串。我使用std::排序(v.begin(),v.end(),比较器)。然后用相同的参数调用std::is_sorted。结果是假的,为什么呢?

代码语言:javascript
复制
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <iterator>
#include <cassert>
int main(){
    auto comparator([](std::string a , std::string b) {return a.length() - b.length();} );
    std::vector<std::string> v {"y" , "yyyy" , "yy" ,
                                 "yy" , "yyyyyyy" , "yyy"};
    assert(false == std::is_sorted(v.begin() , v.end(),comparator));
    std::sort(v.begin(), v.end(),comparator);
    assert(true == std::is_sorted(v.begin() , v.end(),comparator));
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-06-20 14:14:03

您的谓词不能正常工作。如果您打算按字符串长度进行排序,则需要

代码语言:javascript
复制
auto comparator([](std::string a , std::string b) {return a.length() < b.length();} );

您提交的原始谓词返回字符串长度差,它是整型的,在被std::sort调用时可以转换为std::sort,并且对于与0false不同的所有东西都会产生true。因此,每个不相等的字符串长度都会导致谓词被求值为true,而具有不同字符串长度的序列元素将由于谓词始终为"true“而被无限交换。这将导致未定义的行为。

这里的术语是谓词必须实现“严格弱排序”,例如在优先选择上。感谢@Fran oisAndrieux和@Peter在这方面的评论。

还可以考虑通过const std::string&std::string_view传递参数,以避免不必要的副本。

票数 7
EN

Stack Overflow用户

发布于 2019-06-20 14:35:38

按照C++标准(28.7排序及相关操作)

2比较是函数对象类型(23.14)。应用于类型比较对象的函数调用操作的返回值,当上下文转换为bool时(第7条),如果调用的第一个参数小于第二个参数,则为true,否则为false。假定排序关系的算法始终使用比较法。假设comp不会通过取消引用的迭代器应用任何非常数函数。

这个lambda表达式

代码语言:javascript
复制
auto comparator([](std::string a , std::string b) {return a.length() - b.length();} );

如果两个字符串的长度不等,则始终返回(上下文转换的值) true

所以对于这个向量

代码语言:javascript
复制
std::vector<std::string> v {"y" , "yyyy" , "yy" ,
                             "yy" , "yyyyyyy" , "yyy"};

lambda表达式在位置false3处返回相邻元素"yy""yy""yy"

例如,如果您将中间值放置在位置2和3之间,例如

代码语言:javascript
复制
std::vector<std::string> v {"y" , "yyyy" , "yy" , "y",
                             "yy" , "yyyyyyy" , "yyy"};

然后第一个断言

代码语言:javascript
复制
assert(false == std::is_sorted(v.begin() , v.end(),comparator));

失败了。

因此,需要正确地定义比较函数。例如

代码语言:javascript
复制
auto comparator( []( const std::string &a , const std::string &b ) 
                 {
                     return a.length() < b.length(); 
                 } );

此外,lambda表达式的参数应该是常量引用。

考虑到,如果编译器支持C++ 17,那么还可以通过以下方式重写lambda表达式

代码语言:javascript
复制
auto comparator( []( const std::string &a , const std::string &b ) 
                 {
                     return std::size( a ) < std::size( b ); 
                 } );
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56687913

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档