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

Cod*_*ith 102 c++

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

第二部分,如果我要设计一个比较两个类型对象的比较方法,Foo我只想返回-1,0或1,是否会使用shortchar通常是一个好主意?

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

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

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

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

Jam*_*nze 113

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

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

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

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

short a = 1;
std::cout << sizeof( a ) << std::endl;
std::cout << sizeof( a + 0 ) << std::endl;
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

  • 如果你能在你的答案中解释更多关于"返回值是rvalues,受积分促销"的话,那就太好了. (46认同)
  • @AlvinWong:请参阅[为什么C字符文字是整数而不是字符?](http://stackoverflow.com/questions/433895/why-are-c-character-literals-ints-instead-of-chars? rq=1) 了解更多背景信息。 (2认同)

Mat*_*son 41

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

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

int compare(int *a, int *b)
{
   return *a - *b;
}
Run Code Online (Sandbox Code Playgroud)

这比以下更麻烦:

int compare(int *a, int *b)
{
   if (*a == *b) return 0;
   if (*a > *b) return 1;
   return -1;
}
Run Code Online (Sandbox Code Playgroud)

如果你必须返回-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;
}
Run Code Online (Sandbox Code Playgroud)

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

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();
}
Run Code Online (Sandbox Code Playgroud)

  • 你的第一个`compare`函数有溢出问题(幸运的是)如果需要`char*`并且`char`小于`int`则不适用.例如,如果`*a`是'MAX_INT`并且`*b`是`-1`那么`*a - *b`是UB,但是如果实现选择定义它的行为,那么结果几乎肯定是否定的. (8认同)

Tob*_*bia 25

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

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

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


Ale*_*ain 10

这是一个C-ism.

当C必需compare类型函数时,它们总是返回一个int.C++刚刚推进了这项工作(不幸的是).

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


Jon*_*Jon 10

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

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


BЈо*_*вић 5

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

没问题。更好的方法是返回 bool (如果只想比较是否相等)或 enum (有关更多信息):

enum class MyResult
{
  EQUAL,
  LESS,
  GREATER
};

MyResult AreEqual( const Foo &foo1, const Foo & foo2 )
{
  // calculate and return result
}
Run Code Online (Sandbox Code Playgroud)

  • “没问题”。你有理由这样做吗? (3认同)