【发布时间】:2018-08-23 06:19:38
【问题描述】:
在处理一个项目时,我遇到了以下我无法向自己解释的问题。
我有以下is_in_set(..) function,它只是检查一个 cstring 是否在一个 unordered_set 的 cstrings 中:
bool is_in_set(const char * str, std::unordered_set<const char *> the_set)
{
if ( the_set.find( str ) != the_set.end() )
return true;
else
return false;
}
然后我创建了以下示例 main 方法来演示我的问题:
int main()
{
std::unordered_set<const char *> the_set({"one",
"two", "three", "four", "five"});
std::string str = "three";
const char * cstr = "three";
std::cout << "str in set? "
<< is_in_set( str.c_str() , the_set ) << std::endl
<< "cstr in set? "
<< is_in_set( cstr, the_set ) << std::endl;
const char * str_conv = str.c_str();
std::cout << "str_conv in set? "
<< is_in_set( str_conv , the_set ) << std::endl
<< "strcmp(str_conv, cstr) = " << strcmp( str_conv , cstr )
<< std::endl;
return 0;
}
我希望上面的代码能够找到转换为 const char* 的 std::string 以及集合中的 cstring。 相反,它会生成以下输出(Visual Studio Community 2017):
str in set? 0
cstr in set? 1
str_conv in set? 0
strcmp(str_conv, cstr) = 0
我还在这两个变量上运行了一个 for 循环,为每个变量逐字节输出(以十六进制表示),结果如下:
74 68 72 65 65 00 = c_str
74 68 72 65 65 00 = str_conv
为什么在集合中找不到转换为 const char * 的 std::string? 在这种情况下 strcmp 不应该返回一个不同于 0 的值吗?
【问题讨论】:
-
如果同一个字符串在不同的地方有两个副本,那么地址显然会不同。您不能通过比较地址来比较 C 字符串。你为什么不做一套
std::strings?如果你真的想让它工作,你必须提供一个自定义比较器。阅读unordered_set文档以了解如何操作。 -
请注意,您能够在您的集合中找到
cstr,因为您的编译器意识到两个字符串文字具有相同的值并将它们合并为一个。此行为不可移植。 -
std::unordered_set::find搜索匹配的const char*值,而不查看它们指向的值。如果您希望进行自定义比较,请考虑在构造时将键相等和散列的自定义谓词传递给std::unordered_set。
标签: c++ string c++11 visual-studio-2017 unordered-set