这两个比较表达式相同吗?
Are these two comparison expressions identical?
关于这两个函数是否具有相同的逻辑,似乎有一些分歧:
bool operator<(const screenPoint& left, const screenPoint& right){
if (left.x < right.x) return true;
else return left.y < right.y;
}
bool operator<(const screenPoint& left, const screenPoint& right){
return left.x < right.x || left.y < right.y;
}
我盯着它们看了很长一段时间,我看不出它们的行为会有什么不同。在两者中,如果是left.x < right.x
,它们都返回true
。如果不是,那么它们都返回left.y < right.y
的结果。对吧?
如果没有,谁能详细说明一下。
另外,有人认为第一个与std::tie
中词法排序的实现相同,这是真的吗?
这两个是完全相同的(如果你在第一个if
中修复了缺少的括号),但是它们没有实现严格的弱排序,所以你可能不想使用它们(在标准有序的容器和算法中使用它们是无效的)。
证明:考虑a=(1,3) b=(2,2)的原关系。然后是<A.(违反非对称属性)>
正确的字典顺序应该是这样的:
bool operator<(const screenPoint& left, const screenPoint& right){
if (left.x < right.x)
return true;
if (left.x > right.x)
return false;
return left.y < right.y;
}
如果成员只有<
操作符而没有>
操作符,则将left.x > right.x
替换为!(right.x < left.x)
。这就是std::pair
和std::tuple
(由std::tie
返回)实现字典比较的方式。
不要只是猜测,让你的编译器发出asm代码来检查差异。我的编译器(clang)对两个版本产生相同的结果:
#include <tuple>
__attribute__((noinline)) bool operatorLess1(const screenPoint& left, const screenPoint& right)
{
if (left.x < right.x) return true;
else return (left.y < right.y);
}
__attribute__((noinline)) bool operatorLess2(const screenPoint& left, const screenPoint& right)
{
return left.x < right.x || left.y < right.y;
}
__attribute__((noinline)) bool operatorLess3(const screenPoint& left, const screenPoint& right)
{
return std::tie(left.x, left.y) < std::tie(right.x, right.y);
}
__attribute__((noinline)) bool operatorLess4(const screenPoint& left, const screenPoint& right)
{
if (left.x < right.x) return true;
else if (left.x > right.x) return false;
else return (left.y < right.y);
}
编制clang++ -S -masm=intel -std=c++11 -O2 a.cpp
收益率:
__Z13operatorLess1RK11screenPointS1_: ## @_Z13operatorLess1RK11screenPointS1_
push rbp
mov rbp, rsp
Ltmp2:
movss xmm0, dword ptr [rsi] ## xmm0 = mem[0],zero,zero,zero
mov al, 1
ucomiss xmm0, dword ptr [rdi]
ja LBB0_2
movss xmm0, dword ptr [rsi + 4] ## xmm0 = mem[0],zero,zero,zero
ucomiss xmm0, dword ptr [rdi + 4]
seta al
LBB0_2:
pop rbp
ret
.cfi_endproc
__Z13operatorLess2RK11screenPointS1_: ## @_Z13operatorLess2RK11screenPointS1_
.cfi_startproc
push rbp
mov rbp, rsp
Ltmp5:
movss xmm0, dword ptr [rsi] ## xmm0 = mem[0],zero,zero,zero
mov al, 1
ucomiss xmm0, dword ptr [rdi]
ja LBB1_2
movss xmm0, dword ptr [rsi + 4] ## xmm0 = mem[0],zero,zero,zero
ucomiss xmm0, dword ptr [rdi + 4]
seta al
LBB1_2:
pop rbp
ret
.cfi_endproc
__Z13operatorLess3RK11screenPointS1_: ## @_Z13operatorLess3RK11screenPointS1_
push rbp
mov rbp, rsp
Ltmp8:
movss xmm0, dword ptr [rdi] ## xmm0 = mem[0],zero,zero,zero
movss xmm1, dword ptr [rsi] ## xmm1 = mem[0],zero,zero,zero
mov al, 1
ucomiss xmm1, xmm0
ja LBB2_4
ucomiss xmm0, xmm1
jbe LBB2_3
xor eax, eax
pop rbp
ret
LBB2_3:
movss xmm0, dword ptr [rsi + 4] ## xmm0 = mem[0],zero,zero,zero
ucomiss xmm0, dword ptr [rdi + 4]
seta al
LBB2_4: ## %_ZNSt3__1ltIJRKfS2_EJS2_S2_EEEbRKNS_5tupleIJDpT_EEERKNS3_IJDpT0_EEE.exit
pop rbp
ret
.cfi_endproc
__Z13operatorLess4RK11screenPointS1_: ## @_Z13operatorLess4RK11screenPointS1_
.cfi_startproc
push rbp
mov rbp, rsp
Ltmp11:
movss xmm0, dword ptr [rdi] ## xmm0 = mem[0],zero,zero,zero
movss xmm1, dword ptr [rsi] ## xmm1 = mem[0],zero,zero,zero
mov al, 1
ucomiss xmm1, xmm0
ja LBB3_4
ucomiss xmm0, xmm1
jbe LBB3_3
xor eax, eax
pop rbp
ret
LBB3_3:
movss xmm0, dword ptr [rsi + 4] ## xmm0 = mem[0],zero,zero,zero
ucomiss xmm0, dword ptr [rdi + 4]
seta al
LBB3_4:
pop rbp
ret
.cfi_endproc
可以看到,前两个版本是相同的,它们将比较x
或直接比较y
。相反,正如interjay所指出的,std::tie
版本是一个完全弱排序,当left.x > left.y
返回0。实际上,它的代码与operatorLess4
相同。
相关文章:
- 使用 boost::regex (c++) 比较两个正则表达式
- 符号和未签名整数表达式之间的比较,以进行循环误差
- C++编译错误(有符号和无符号整数表达式之间的比较)
- C++ 有符号和无符号整数表达式之间的比较
- C++ 斯特劳斯特鲁普的"std_lib_facilities.h"字符串结构 – 警告:无符号表达式的比较
- 指针对象使用CPP中的指针表达式进行比较
- 有符号和无符号整数表达式之间的比较
- 如何在不使用 lambda 表达式的情况下实现特定的比较器
- 消除有符号和无符号整数表达式之间比较的优雅方式
- 在文件中找到最长的行,签名和未签名的整数表达式之间的比较
- C++比较表达式错误
- C++17中的折叠表达式-比较运算符的用例
- 与表达式或变量进行比较之间的性能差异
- C 11:比较lambda表达式
- 我的 lambda 表达式进行映射键比较有什么问题?
- C++与赋值表达式的比较是右侧表达式
- 警告:有符号和无符号整数表达式之间的比较
- 条件语句在比较表达式时的基础是什么?
- "二进制表达式的操作数无效..."尝试比较regex_iterators时
- 我想一次将一个字符串与许多不同的正则表达式进行比较