c++ - 当应用于不相关的指针时,std::less 如何比 < 更安全?
问题描述
我发现我应该使用std::less
来比较我的对象,以便能够比较不相关的指针(来自不同的序列),因为<
如果在那些不相关的指针上使用关系运算符,则只使用关系运算符就会产生 UB。
所以为了练习我已经实现了我的
compare
功能:#include <iostream> using namespace std; #include <functional> template <class T> constexpr int compare(T const& x, T const& y) { if(std::less<T>()(x, y)) return -1; if(std::less<T>()(y, x)) return 1; return 0; } int main() { std::cout << compare(std::string("Hello"), std::string("hello")) << std::endl; std::cout << compare(std::string("hello"), std::string("Hello")) << std::endl; std::cout << compare(std::string("hello"), std::string("hello")) << std::endl; std::cout << compare(-7, 1) << std::endl; int* p1{new int(10)}; int* p2{new int{4}}; std::cout << compare(p2, p1) << std::endl; std::cout << "\ndone!\n"; }
输出:
-1
1
0
-1
1
为什么我不应该在这种情况下直接使用
<
?怎么可能
std::less
比 更安全<
?我是说内部结构。谢谢!
解决方案
怎么可能
std::less
比 更安全<
?
因为标准是这样说的。
我是说内部结构。
在所有 x64 和大多数现代架构std::less::operator()
上只是对内置运算符的简单包装,<
或者将指针转换为uinptr_t
然后进行比较。
C++ 旨在适用于各种硬件架构,因此大概有一些架构(历史?,古老?,奇怪?)并非所有数据地址都(容易)可比较。在那些架构上,操作员<
将无法工作,而std::less
需要实现工作方式。
作为旁注,您没有在示例中比较指针
我应该使用
std::less
而不是<
对于指向(可能)不同对象或不同数组中的指针,是的,否则如果您<
在这种情况下使用,则您有未定义的行为。对于其他任何事情都没有。std::less
当您需要将比较器功能提供给其他一些功能(例如std::sort
)时,它最有用。
例如:
int a{}, b{}
int* p_a = &a;
int* p_aa = &a;
int* p_b = &b;
p_a < p_b; // technically Undefined Behavior, use std::less instead:
std::less<>{}(p_a, p_b);
p_a < p_a; // ok
p_a < p_aa; // ok
int arr1[10]{}
int* p1_1 = &arr1[0];
int* p1_2 = &arr1[5];
int arr2[10]{};
int* p2_1 = &arr2[0];
int* p2_2 = &arr2[5];
p1_1 < p2_1; // technically Undefined Behavior, use std::less instead:
std::less<>{}(p_1_1, p_2_1);
p1_1 < p1_2; // ok
p2_1 < p2_2; // ok
char str[] = "hello";
char* str_end = str + strlen(str);
for (char* p = str; p < str_end; ++p) // ok
// ...
用于其他任何用途<
int a{}, b{};
a < b; // ok
std::string s1{}, s2{};
s1 < s2; // ok
推荐阅读
- r - 如何在除一个向量之外的所有元素上循环函数并将结果存储在数据框的单独列中
- curl - 使用 -d 命令时卷曲意外令牌
- amazon-web-services - AWS EKS:用户无权执行:iam:CreateRole on resource
- css - 在实时 sass 编译器中编译时出现 Sass 无效 css 错误
- javascript - 在完成 xmlhttprequest 之前调用外部函数
- html - 无法始终如一地获得结果,chrome dev tools 中的文本发生变化,下拉选择器无法工作
- reactjs - 如何在 React Jodit 编辑器中通过 URL 输入禁用上传图像?
- azure-data-factory - 将 ForEach SQL 加载到 Azure 数据工厂中的单个 CSV
- angular - Angular:全局 ErrorHandler 中的多种材质小吃吧
- c++ - 在返回 char 数组的函数中返回警告的局部变量的地址