为什么string :: compare返回一个int?
为什么string::compare
返回一个int而不是像short
或char
这样的较小types? 我的理解是,这种方法只返回-1,0或1。
第二部分,如果我devise一个比较两个Foo
types对象的比较方法,我只想返回-1,0或1,那么使用short
或char
通常是个好主意?
编辑:我已被纠正, string::compare
不会返回-1,0或1,它实际上返回一个值> 0,<0或0.谢谢让我排队。
似乎答案是粗略的,没有理由返回比int更小的types,因为返回值是“rvalues”,而那些“rvalues”不会比inttypes(4字节)小。 另外,很多人指出大多数系统的寄存器大小可能会变大,因为无论你给它们一个1,2或者4个字节的值,这些寄存器都将被填满,返回没有真正的好处一个较小的值。
编辑2:实际上,当使用较小的数据types(比如alignment,屏蔽等)时,看起来可能会有额外的处理开销。一般的共识是,处理大量数据时存在较小的数据types以节省内存,如一个数组的情况。
今天学了一些东西,再次感谢你们!
首先,规范是返回一个小于,等于或大于0
,不一定是-1
或1
。 其次,返回值是rvalues,受到整体提升的影响,所以返回更小的东西没有意义。
在C ++中(如在C中),每个expression式都是右值或左值。 从历史上看,这些术语指的是左值出现在赋值左边的情况,右值只能出现在右边。 今天,非类types的一个简单的近似值是左值在内存中有一个地址,右值不是。 因此,你不能取一个右值的地址,并且cv-qualifiers(条件是“access”)不适用。 用C ++来说,没有types的右值是一个纯粹的值,而不是一个对象。 函数的返回值是一个右值,除非它具有引用types。 (适合在寄存器中的非typestypes几乎总是被返回到寄存器中,例如,而不是在内存中)。
对于类types来说,由于可以在右值上调用成员函数,所以问题有点复杂。 这意味着右值必须实际上具有地址,对于this
指针,并且可以是cv限定的,因为cv限定在重载parsing中起作用。 最后,C ++ 11引入了几个新的区别,以支持右值引用; 这些也主要适用于class级types。
积分式提升是指在expression式中使用小于int
整数types作为右值时,在大多数情况下,它们将被提升为int
。 所以,即使我有一个variables声明short a, b;
在expression式a + b
, a
和b
在加法发生之前被提升为int
。 同样,如果我写a < 0
,则比较是在a的值上完成a
,转换为int
。 在实践中,很less有这种情况发生,至less在2的补码机器中,整数算术包装(即除了极less数的外来物,今天 – 我认为Unisys大型机是唯一的例外)。 即使在更常见的机器上:
short a = 1; std::cout << sizeof( a ) << std::endl; std::cout << sizeof( a + 0 ) << std::endl;
应该给出不同的结果:第一个是相当于sizeof( short )
,第二个sizeof( int )
(因为整数提升)。
这两个问题是正式正交的; 右值和左值与整体提升无关。 除 …积分促销只适用于右值,而大多数(但不是全部)您将使用右值的情况将导致整数升级。 出于这个原因,真的没有理由返回一个小于int
的数值。 甚至有一个很好的理由不把它作为字符types返回。 像<<
这样的重载操作符对于字符types的行为往往是不同的,所以你只想返回字符作为字符types。 (你可以比较一下:
char f() { return 'a'; } std::cout << f() << std::endl; // displays "a" std::cout << f() + 0 << std::endl; // displays "97" on my machine
不同之处在于,在第二种情况下,加法引起整体提升,导致<<
被select的不同超载。
这是故意的,它不返回-1,0或1。
它允许(注意这不是用于string,但它同样适用于string)
int compare(int *a, int *b) { return *a - *b; }
这比以下的麻烦less很多:
int compare(int *a, int *b) { if (*a == *b) return 0; if (*a > *b) return 1; return -1; }
如果必须返回-1,0或1,那么这是你必须做的(或者沿着这些线)。
它也适用于更复杂的types:
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; }
在string的情况下,我们可以这样做:
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(); }
int 通常 (意味着在大多数现代硬件上)与系统总线和/或CPU寄存器相同大小的整数,即所谓的机器字。 因此int通常比较小的types传递的更快,因为它不需要alignment,屏蔽和其他操作。
较小的types主要用于为数组和结构提供RAM使用优化。 在大多数情况下,它们交换几个CPU周期(以alignment操作的forms)以获得更好的RAM使用。
除非你需要强制你的返回值是一个中等大小(char,short …)的有符号或无符号数字,否则你最好使用int,这就是为什么标准库会这样做。
这是一个C-ISM。
当C需要compare
types函数时,它们总是返回一个int
。 C ++刚刚推出(不幸)。
但是,返回int
实际上可能是最快的方法,因为它通常是正在使用的系统寄存器的大小。 (故意模糊)
该方法实际上并不返回集合{ -1, 0, 1 }
的整数; 它实际上可以是任何整数值。
为什么? 我能想到的主要原因是int
被认为是build筑的“自然尺寸”价值; 对这个尺寸的值的操作通常至less与对较小或较大值的操作一样快(并且在许多情况下更快)。 所以这是一个允许实现足够的松弛来使用最快的情况。
如果我要devise一个比较两个Footypes对象的比较方法,我只想返回-1,0或1,那么使用short或char通常是个好主意?
这将是好主意。 更好的方法是返回一个布尔(如果只想比较是否相等),或枚举(更多信息):
enum class MyResult { EQUAL, LESS, GREATER }; MyResult AreEqual( const Foo &foo1, const Foo & foo2 ) { // calculate and return result }
假设有些人正在将代码从C更改为C ++。 他们决定将strcmp
replace为string::compare
。
由于strcmp
返回int
,所以string::compare
返回int
更容易。
可能使其工作更像strcmp
这也有这套返回值 。 如果你想要移植代码,可能会更直观地让替代品尽可能靠近。
此外,返回值不仅是-1
或1
而且还有<0
0
或>0
。
另外,正如所提到的,由于回报受到整体提升的影响,因此将其缩小是没有意义的。
因为布尔返回值只能是两个可能的值(true,false),并且比较函数可以返回三个可能的值(小于,等于,大于)。
更新
虽然当然可以返回一个有符号的short,但如果你真的想实现自己的比较函数,你可以用两个布尔值来返回一个半字节或者结构值。