std::转换为常量字符 * 的字符串在 std::unordered_set<const 字符 * 中找不到>
std::string casted to const char * can not be found in an std::unordered_set<const char *>
在做一个项目时,我遇到了以下我无法向自己解释的问题。
我有以下 is_in_set(..( 函数,它只是检查字符串是否在 cstring unordered_set中:
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
为什么在集合中找不到 std::string 转换为 const char *?在这种情况下,strcmp 不应该返回一个不同于 0 的值吗?
对于const char *
,没有按值比较字符串的 ==
运算符重载,因此我相信unordered_set
容器将始终比较指针,而不是指向字符串的值。
作为优化,编译器可以使具有相同字符的多个字符串文本使用相同的内存位置(因此具有相同的指针(,这就是为什么在使用另一个字符串文本时能够找到字符串的原因。但是,通过其他机制构造的任何字符串(即使它包含相同的字符(也不会位于相同的内存位置,因此指针将不相等。
正如@Daniel Pryden指出的那样,您正在进行地址比较。要解决此问题,您需要让unordered_set
存储std::string
对象,或者创建自定义比较以供要使用的unordered_set
。
根据相关问题的答案,如下所示:
struct StringEqual
{
bool operator()(const char* a, const char* b) { return 0 == strcmp(a,b); }
};
std::unordered_set<const char *, std::Hash<const char*>, StringEqual> the_set(
{"one", "two", "three", "four", "five"});
应该做这个伎俩。这为unordered_set
提供了用于测试字符串的更好运算符。
有关Pred
模板参数的详细信息,请参阅文档。
确定在使用哈希表(例如静态变量(或使用new/malloc等分配字符串时不会离开堆栈,请使用std::unordered_set<std::string>
或提供自定义哈希器。
像这样:
struct str_eq {
bool opeator()(const char* lsh, const char rhs) const noexcept
{
return lsh == rhs || 0 == std::strcmp(lsh, rhs);
}
};
struct str_hash {
std::size_t opeator()(const char* str) const noexcept
{
// some mur-mur2, google cityhash hash_bytes etc instead of this
return std::hash<std::string>( std::string(str) ) ();
}
};
typedef std::unordered_set<const char*, str_hash, str_eq, std::allocator<const char*> > my_string_hashset;
- 带有指定长度字符* 参数的 std::regex_search 在 VS2017 中不起作用?
- 在 std::无符号字符的向量处存储 int 的十六进制表示形式
- 从 std::vector<无符号字符>切片中提取 int?
- 字符转换功能 std::isupper() & std::islower() C++17
- 将无符号字符的向量存储在数组中会给我 std::bad_alloc
- 为什么 std::string_view 比常量字符*快?
- std::stringstream 返回字符 *
- 如何将带有十六进制值的 std::string 转换为 std::vector<无符号字符>
- 自定义 std::fstream,std::filebuf 的溢出和下溢函数未为每个字符调用
- 在 c++ 中以十六进制格式打印无符号字符(BYTE).使用 std::cout
- 在 std::vector<无符号字符中存储任意数据的方法>
- 为什么从 std::cin 读取输入后右括号字符的值有时不是")"?
- "std::string"是否将其字符作为签名字符在内部存储?
- std::stoi 只转换前几个字符
- std::可选实现为联合与字符[]/aligned_storage
- C++ 无法将 std::vector<BYTE> 转换为字符串或字符数组
- 如何使用 std::copy 当类有"无符号字符和运算符[]"时
- C++ 从 std::string 中删除所有非数字字符
- 我可以得到一个字符 * 到一个 std::sregex_iterator 匹配 str() 吗?
- 使用 .data() 将字符数组转换为 std::string 不会转换整个数组