为什么string::compare返回int类型?
Why does string::compare return an int?
为什么string::compare
返回int
而不是short
或char
这样的较小类型?我的理解是,这个方法只返回- 1,0或1。
第二部分,如果我要设计一个比较方法,比较两个类型为Foo
的对象,我只想返回- 1,0或1,使用short
或char
通常是一个好主意吗?
string::compare
不返回- 1,0或1,它实际上返回一个值>0,<0或0。谢谢你们让我守规矩。
答案似乎大致是,没有理由返回小于int
的类型,因为返回值是"右值",而这些"右值"不会从小于int类型(4字节)中受益。此外,许多人指出,大多数系统的寄存器的大小可能都是int
,因为无论您给它们1、2或4字节的值,这些寄存器都将被填满,返回更小的值并没有真正的好处。
首先,规范规定它将返回一个值大于、等于或大于0
,不一定是-1
或1
。其次,返回值是右值,服从整型促销,所以返回更小的值没有意义。
在c++中(和C一样),每个表达式要么是右值,要么是右值左值。从历史上看,这些术语指的是左值出现在赋值操作的左侧,其中的右值只能出现在右边。今天,一个简单的近似非类类型是左值在内存中有一个地址右值没有。因此,不能取右值的地址,cv限定符(限定"访问")不适用。在在c++术语中,没有类类型的右值是纯右值值,而不是对象。函数的返回值是一个右值,除非它具有引用类型。(非类类型which在寄存器中匹配几乎总是在寄存器中返回,例如,而不是在内存中)
对于类类型,由于可以对右值调用成员函数。这意味着右值实际上必须有地址,对于this
指针,并且可以是cv限定的,因为cv限定在重载解析中起作用。最后介绍c++ 11几个新的区别,为了支持右值引用;这些也主要适用于类类型。
积分提升是指当积分类型小于int
的值在表达式中用作右值在大多数情况下,他们将被提升到int
。所以即使我有一个变量声明为short a, b;
,在表达式a
+ b
中,a
和b
在添加之前都被提升为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 )
(因为积分促销)。
这两个问题在形式上是正交的;右值和左值与积分推广无关。除了<<em>/em>……积分提升只适用于右值,大多数(但不适用)所有使用右值的情况都会导致积分促销。因为这个原因,真的没有理由返回一个小于int
的数值。甚至有很好的理由不把它作为字符类型。像<<
这样的重载操作符通常表现为字符类型不同,所以你只想返回字符作为字符类型。(你可以比较一下区别:
char f() { return 'a'; }
std::cout << f() << std::endl; // displays "a"
std::cout << f() + 0 << std::endl; // displays "97" on my machine
的区别在于,在第二种情况下,加法有造成积分提升的发生,从而产生不同的结果<<
的过载选择。
不返回-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();
}
int 通常(在大多数现代硬件上的意思)是与系统总线和/或CPU寄存器相同大小的整数,即所谓的机器字。因此,int通常比较小的类型传递得更快,因为它不需要对齐、屏蔽和其他操作。
较小的类型的存在主要是为了优化数组和结构体的内存使用。在大多数情况下,它们会用一些CPU周期(以对齐操作的形式)来换取更好的RAM使用。
除非您需要强制您的返回值是特定大小(char, short…)的有符号或无符号数,否则您最好使用int,这就是标准库这样做的原因。
C-ism。
当C语言需要compare
类型的函数时,它们总是返回一个int
。c++只是把它发扬光大了(很不幸)。
int
实际上可能是最快的方法,因为它通常是正在使用的系统的寄存器的大小。(故意模糊)
该方法实际上并不返回集合{ -1, 0, 1 }
中的整数;它可以是任意整数值
为什么?我能想到的主要原因是int
应该是建筑的"自然大小"值;对这种大小的值的操作通常至少与对较小或较大值的操作一样快(在许多情况下更快)。所以这是一个允许实现足够宽松的例子,可以使用最快的方法。
如果我要设计一个比较方法来比较两个类型为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
}
假设有人正在将代码从C更改为c++。他们决定将strcmp
替换为string::compare
。
因为strcmp
返回int
,所以string::compare
更容易返回int
作为礼物。
可能是为了使它更像strcmp
,也有这组返回值。如果你想移植代码,使用尽可能接近的替换代码可能会更直观。
同样,返回值不只是-1
, 0
或1
,而是<0
, 0
或>0
。
同样,正如前面提到的,由于返回值服从积分提升,因此使其更小是没有意义的。
因为布尔返回值只能是两个可能的值(true, false),而比较函数可以返回三个可能的值(小于,等于,大于)。
虽然可以返回带符号的短值,但如果真的想要实现自己的比较函数,则可以返回带有两个布尔值的nibble或struct值。
- 不能在初始值设定项列表中将非常量表达式从类型 'int' 缩小到'unsigned long long'
- 多维数组 C++ 中数组下标的类型"int[int]"无效
- 指针问题:从不兼容的类型"int"分配给"int *"
- 数组类型 int[n][n] 不可赋值,因为表达式必须具有常量值
- 错误:数组下标的类型"int[int]"无效
- 运行时错误:引用绑定到类型"int"的未对齐地址0xbebebebebebebec6,这需要 4 个字节对齐 (stl_vector.h)
- 类型为 "int*" 的参数与 C++ 中错误类型"int**"参数不兼容
- 类型"int"和"const char [15]"到二进制"运算符<<"的无效操作数^
- 从类型bankAccount的返回值到函数返回类型int没有可行的转换
- for 循环说 - 错误 成员引用基类型"int [13]"不是结构或联合
- 运行时错误:有符号整数溢出:964632435 * 10 无法在类型 'int' 中表示
- 如何增加模板类型 int 参数?
- 尝试使用 Array 类的模板构造整数数组时,错误:为什么数组类型"int [5]"不可分配,
- 如何为底层类型 int 的枚举专门化类
- 数组下标编译的无效类型'int[int]'由于 -Wfatal 错误而终止
- 不能将 "const char*" 类型的值分配给类型 "int" 的实体
- 数组下标的无效类型INT [INT]
- 请求在"伺服控制器"中请求成员"附加",该成员属于非类类型"int"
- 数组类型 'int [8]'不可分配
- 未声明的标识符和类型"int"从 main 调用类时出现意外错误