首页 文章

为什么string :: compare返回一个int?

提问于
浏览
102

为什么string::compare返回 int 而不是像 shortchar 这样的较小类型?我的理解是这个方法只返回-1,0或1 .

第二部分,如果我要设计一个比较两个类型 Foo 的对象的比较方法,而我只想返回-1,0或1,那么使用 short 或_2560135一般是个好主意吗?

编辑:我已经纠正, string::compare 不返回-1,0或1,它实际上返回一个值> 0,<0或0.感谢您让我排队 .

似乎答案是粗略的,没有理由返回小于 int 的类型,因为返回值是"rvalues"而那些"rvalues"不会受益于小于int(4字节)类型 . 此外,许多人指出,无论如何,大多数系统的寄存器大小可能都是 int ,因为无论你给它们一个1,2或4个字节的值,这些寄存器都会被填充,返回没有真正的优势一个较小的值 .

编辑2:事实上,当使用较小的数据类型(如对齐,屏蔽等)时,看起来可能会有额外的处理开销 . 一般的共识是,在处理大量数据时,存在较小的数据类型以节省内存,如数组的情况 .

今天学到了一些东西,再次感谢你们!

9 回答

  • -1

    首先,规范是它将返回小于,等于或大于 0 的值,不一定是 -11 . 其次,返回值是rvalues,受整体提升影响,因此返回任何较小的值都没有意义 .

    在C中(如在C中),每个表达式都是rvalue或lvalue . 从历史上看,这些术语指的是左值出现在赋值左侧的事实,其中右值只出现在右边 . 今天,非类类型的简单近似是左值在内存中有一个地址,右值没有 . 因此,您不能获取rvalue的地址,并且cv-qualifiers(条件“access”)不适用 . 在C术语中,没有类类型的rvalue是纯值,而不是对象 . 函数的返回值是rvalue,除非它具有引用类型 . (适合寄存器的非类型类型几乎总是在寄存器中返回,例如,而不是在内存中 . )

    对于类类型,问题有点复杂,因为您可以在右值上调用成员函数 . 这意味着对于 this 指针,rvalues实际上必须具有地址,并且可以是cv限定的,因为cv-qualification在重载解析中起作用 . 最后,C 11引入了几个新的区别,以支持右值引用;这些也主要适用于 class 类型 .

    积分促销是指当小于 int 的整数类型用作表达式中的rvalues时,在大多数情况下,它们将被提升为 int . 因此即使我有一个变量声明为 short a, b; ,在表达式 a + b 中, ab 都会在添加之前被提升为 int . 同样,如果我写 a < 0 ,则对 a 的值进行比较,转换为 int . 在实践中,很少有这种情况会有所不同,至少在2的补码机上整数算术包装(即除了极少数外来物,今天 - 我认为Unisys大型机是唯一的例外) . 即便在更常见的机器上:

    short a = 1;
    std::cout << sizeof( a ) << std::endl;
    std::cout << sizeof( a + 0 ) << std::endl;
    

    应该给出不同的结果:第一个相当于 sizeof( short ) ,第二个 sizeof( int ) (因为整体推广) .

    这两个问题正式正交; Value 和左值与整体促销无关 . 除了......整体促销仅适用于 Value ,并且大多数(但不是全部)您将使用 Value 的情况将导致整体促销 . 因此,实际上没有理由在小于 int 的值中返回数值 . 甚至有一个很好的理由不将它作为字符类型返回 . 重载的运算符(如 << )通常对字符类型的行为有所不同,因此您只想将字符作为字符类型返回 . (你可以比较差异:

    char f() { return 'a'; }
    std::cout << f() << std::endl;      //  displays "a"
    std::cout << f() + 0 << std::endl;  //  displays "97" on my machine
    

    不同之处在于,在第二种情况下,添加导致整体促销发生,这导致选择不同的超载 << .

  • 2

    它是故意不返回-1,0或1 .

    它允许(注意这不是字符串,但它同样适用于字符串)

    int compare(int *a, int *b)
    {
       return *a - *b;
    }
    

    这比以下更麻烦:

    int compare(int *a, int *b)
    {
       if (*a == *b) return 0;
       if (*a > *b) return 1;
       return -1;
    }
    

    如果你必须返回-1,0或1,这就是你必须要做的[或者沿着这些方向的东西] .

    它也适用于更复杂的类型:

    class Date
    {
        int year;
        int month;
        int day;
    }
    
    int compare(const Date &a, const Date &b)
    {
       if (a.year != b.year) return a.year - b.year;
       if (a.month != b.month) return a.month - b.month;
       return a.day - b.day;
    }
    

    在字符串的情况下,我们可以这样做:

    int compare(const std::string& a, const std::string& b)
    {
       int len = min(a.length(), b.length());
    
       for(int i = 0; i < len; i++)
       {
          if (a[i] != b[i]) return a[i] - b[i];
       }
       // We only get here if the string is equal all the way to one of them
       // ends. If the length isn't equal, "longest" wins. 
       return a.length() - b.length();
    }
    
  • 113

    int通常(意思是在大多数现代硬件上)与系统总线和/或cpu寄存器大小相同的整数,即所谓的机器字 . 因此,int通常比较小的类型传递得更快,因为它不需要对齐,屏蔽和其他操作 .

    较小的类型主要用于允许对数组和结构进行RAM使用优化 . 在大多数情况下,它们会交换几个CPU周期(以对齐操作的形式)以获得更好的RAM使用率 .

    除非您需要将返回值强制为有符号或无符号数的centain大小(char,short ...),否则最好使用int,这就是标准库执行此操作的原因 .

  • 4

    It's a C-ism.

    当C需要 compare 类型的函数时,它们总是返回 int . C只是向前推进(不幸的是) .

    但是,返回 int 实际上可能是最快的方式,因为它通常是正在使用的系统寄存器的大小 . (故意模糊 . )

  • 10

    该方法实际上并不返回set { -1, 0, 1 } 中的整数;它实际上可以是任何整数值 .

    为什么?我能想到的主要原因是 int 应该是架构的"natural size"值;对这个大小的值的操作通常至少与较小或较大值上的操作一样快(并且在许多情况下更快) . 所以这是一个允许实现足够松弛使用最快的东西的情况 .

  • 25

    如果我要设计一个比较两个Foo类型对象的比较方法,我只想返回-1,0或1,那么使用short或char通常是个好主意吗?

    这可能是个好主意 . 更好的方法是返回bool(如果只想比较,如果相等)或枚举(更多信息):

    enum class MyResult
    {
      EQUAL,
      LESS,
      GREATER
    };
    
    MyResult AreEqual( const Foo &foo1, const Foo & foo2 )
    {
      // calculate and return result
    }
    
  • 41

    假设有些人正在将代码从C更改为C.他们决定将 strcmp 替换为 string::compare .

    由于 strcmp 返回 int ,因此作为礼物更容易 string::compare 返回 int .

  • 4

    可能使它更像 strcmp ,它也有set of return values . 如果您想要移植代码,那么更换可能会更直观,以便尽可能地切割 .

    此外,返回值不仅仅是 -101 ,而是 <00>0 .

    此外,正如所提到的那样,由于回报受到integral promotion的影响,因此将其缩小是没有意义的 .

  • 10

    因为布尔返回值只能是两个可能的值(true,false),而compare函数可以返回三个可能的值(小于,等于,大于) .

    Update

    虽然肯定可以返回一个签名的short,如果你真的想要实现自己的compare函数,你可以返回一个含有两个布尔值的半字节或结构值 .

相关问题