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

时间:2013-03-11 12:25:31

标签: c++

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

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

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

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

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

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

9 个答案:

答案 0 :(得分:113)

首先,规范是它将返回一个较小的值 ,等于或大于0,不一定是-11。 其次,返回值是rvalues,受积分影响 促销,所以返回任何小东西都没有意义。

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

对于类类型,问题有点复杂,因为 事实上你可以在右值上调用成员函数。这个 意味着rvalues实际上必须具有this的地址 指针,并且可以是cv-qualified,因为cv-qualification 在超载分辨率中起作用。最后,C ++ 11介绍了 几个新的区别,以支持右值参考; 这些也主要适用于班级类型。

积分促销是指积分类型的事实 小于int用作表达式中的rvalues,in 在大多数情况下,他们将被提升为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 )(因为 整体推广)。

这两个问题正式正交;价值和左值 与整体推广无关。 ... 积分促销仅适用于rvalues和大多数(但不是 所有)你将使用右值的情况将导致 整体推广。因此,没有理由 返回小于int的数值。 甚至有一个很好的理由不把它归还 一个字符类型。像<<这样的重载运算符经常表现出来 不同的字符类型,所以你只想返回 字符作为字符类型。 (你可以比较一下 差:

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

不同之处在于,在第二种情况下,增加了 导致整体促销发生,从而导致不同 要选择的<<超载。

答案 1 :(得分:41)

故意不返回-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();
}

答案 2 :(得分:25)

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

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

除非你需要强制你的返回值是一个有符号或无符号数的centain大小(char,short ...)你最好使用int,这就是标准库的原因。

答案 3 :(得分:10)

这是一个C-ism。

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

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

答案 4 :(得分:10)

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

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

答案 5 :(得分:4)

  

如果我要设计一个比较两个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
}

答案 6 :(得分:4)

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

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

答案 7 :(得分:2)

可能使其更像strcmp,也有set of return values。如果你想要移植代码,那么让替换尽可能接近的可能会更直观。

此外,返回值不仅仅是-101,还有<00>0

另外,正如所提到的,因为返回受integral promotion的限制,所以将其缩小是没有意义的。

答案 8 :(得分:-1)

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

<强>更新

虽然肯定可以返回一个签名的短片,如果真的想要实现你自己的比较函数,你可以返回带有两个布尔值的半字节或结构值。