带有char*键的C++无序映射会产生意外行为
C++ unordered_map with char* key produces unexpected behavior
我试图使用一个无序映射将char*键散列为一个整数值。在编写了自定义函数来散列和比较char*之后,无序映射似乎可以工作了。然而,我最终注意到散列偶尔会返回不正确的结果。我创建了一个测试项目来重现错误。下面的代码创建了一个带有char*键和自定义函数的无序映射。然后,它运行1000x个循环,并记录发生的任何哈希错误。我想知道我的函子是否有问题,或者问题是否存在于无序映射中。如有任何帮助,我们将不胜感激。谢谢
#include <cstdlib>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <tr1/unordered_map>
using namespace std;
//These varaibles are just used for printing the status.
static const char* c1;
static const char* c2;
static int cmpRet;
static int cmpVal;
static const char* hashChar;
static size_t hashVal;
// Character compare functor.
struct CmpChar {
bool operator()(const char* s1, const char* s2) const {
c1 = s1;
c2 = s2;
cmpVal = strcmp(s1, s2);
cmpRet = (cmpVal == 0);
return cmpRet;
}
};
// Hash functor.
struct HashChar {
size_t operator()(const char* str) const {
hashChar = str;
size_t hash = 0;
int c;
while (c = *str++)
hash = c + (hash << 6) + (hash << 16) - hash;
hashVal = hash;
return hash;
}
};
void printStatus() {
printf("'%s' was hashed to: '%lu'n", hashChar, hashVal);
printf("strcmp('%s','%s')='%d' and KeyEqual='%d'n", c1, c2, cmpVal, cmpRet);
}
int main(int argc, char** argv) {
// Create the unordered map.
tr1::unordered_map<const char*, int, HashChar, CmpChar > hash_map;
hash_map["apple"] = 1;
hash_map["banana"] = 2;
hash_map["orange"] = 3;
// Grab the inital hash value of 'apple' to see what it hashes to.
char buffer[256];
bzero(buffer, sizeof (buffer));
strcpy(buffer, "apple");
if (hash_map[buffer] == 1) {
printf("First hash: '%s'=1n", buffer);
}
printStatus();
// Create a random character
srand((unsigned int) time(NULL));
char randomChar = (rand() % 26 + 'a');
// Use the hash 1000x times to see if it works properly.
for (int i = 0; i < 1000; i++) {
// Fill the buffer with 'apple'
bzero(buffer, sizeof (buffer));
strcpy(buffer, "apple");
// Try to get the value for 'apple' and report an error if it equals zero.
if (hash_map[buffer] == 0) {
printf("n****Error: '%s'=0 ****n", buffer);
printStatus();
}
// Fill the buffer with a random string.
bzero(buffer, sizeof (buffer));
buffer[0] = randomChar;
buffer[1] = ' ';
// Hash the random string.
// ** Taking this line out removes the error. However, based on the functors
// it should be acceptable to reuse a buffer with different content.
hash_map[buffer];
// Update the random character.
randomChar = (rand() % 26 + 'a');
}
printf("done!n");
return EXIT_SUCCESS;
}
在容器中使用char*时必须非常小心,因为char*不会像您希望的那样被复制。
通过使用unordered_map的运算符[],映射中用作键的不是您想要的字符串。
operator[]应该将键插入到映射中,通过调用默认构造函数来复制它(请参阅参考),在这种情况下,它只会复制buffer[0]。
因此,之后,你的方法CmpChar将有一个奇怪的行为,因为它将在密钥中读取的下一个字节可以是任何东西。
如果使用字符串对象,就不会有这样的问题。
相关文章:
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- 将函数类成员映射到类本身内部
- 如何在 C# 中映射双 C 结构指针?
- 如何在C++中使用结构生成映射
- 使用std::函数映射对象方法
- 如何加载(或映射)文件部分的最大大小,但适合在Windows上的RAM
- C++映射分割错误(核心转储)
- 内联映射初始化的动态atexit析构函数崩溃
- 使用"std::unordereded_map"映射到"std::list"对象
- 如何从多映射中删除特定的重复项
- 在未初始化映射的情况下,将值插入到映射的映射中
- QT通过C++添加映射QML项目
- 在C++中对T*类型执行std::move的意外行为
- 在c++中访问int到类对象的映射时出错
- 在C++中搜索嵌套多映射值
- 错误处理.将系统错误代码映射到泛型
- 错误 C2760:语法错误:映射迭代器上意外的标记"标识符",预期的";"
- 带有char*键的C++无序映射会产生意外行为
- 使用循环和函数向映射中插入值时的意外行为