我有一个模拟过滤器的unordered_map
,它的key和value分别为std::string_view
,现在假设我想比较两个具有相同键值对的过滤器:它们是否总是相等?
我的想法如下:编译器会尽最大努力将具有相同字节信息的const char* 合并到二进制文件中的一个位置,因此在特定的翻译单元中,字符串文字地址总是匹配的。稍后我会将这些地址传递到std::string_view的构造函数中。当然,由于std::string_view没有实现比较operator==()
,编译器会对类进行字节比较,只有当地址和长度完全匹配时,std::string_view才会比较相等。
然而:如果我在这个翻译单元之外示例化一个与第一个过滤器内容完全相同的过滤器,并在稍后将这些文件链接在一起,会发生什么?编译器是否能够超越TU边界进行查看并合并字符串文字位置?或者相等比较是否会失败,因为底层的字符串视图对于各自的字符串文字将具有不同的地址?
演示
#include <unordered_map>
#include <string_view>
#include <cstdio>
using filter_t = std::unordered_map<std::string_view, std::string_view>;
int main()
{
filter_t myfilter = {{ "key1", "value"}, {"key2", "value2" }};
filter_t my_second_filter = {{ "key1", "value"}, {"key2", "value2" }};
if (my_second_filter == myfilter) {
printf("filters are the same!\n");
}
}
2条答案
按热度按时间djmepvbi1#
当然,由于std::string_view不实现比较运算符==(),compyler将对类进行字节比较
如果没有
operator==
重载(或者因为C20重写了候选重载,例如operator<=>
)可用于一个类类型,那么就不可能将该类型与==
进行比较。即使对于非类类型,内置的
==
也从不执行对象表示的按位/按字节比较(即对象所占用的存储字节的值)。内置的==
总是执行对象所持有的 * 值 * 的比较。对对象表示进行字节比较的唯一方法是显式地使用
operator==
(或==
可重写的重载)来执行此比较。(例如,memcmp
)。因为这显然对std::string_view
没有意义(或大多数类型),标准库不会像那样定义std::string_view
的operator==
。(C20起为operator<=>
),以正确地执行它所引用的字符串的比较,作为一个值,而不是作为字符串文字或字符数组的标识,请参见https://en.cppreference.com/w/cpp/string/basic_string_view/operator_cmp。ohfgkhjo2#
等号比较是按内容而不是按地址匹配的,因此等号运算仍然有效,但可能有两个字符串副本,这取决于编译器的优化。