C++、内存和数组.创建我自己的练习哈希图.内存中留下的意外数据
C++, memory and arrays. Creating my own hashmap for exercise. Unexpected data left in memory?
所以我正在尝试为一个我试图学习 c++ 的小项目创建一个非常具体的需要哈希图。我有以下代码:
template<class T>
class HashMap
{
public:
HashMap();
virtual ~HashMap();
void add(T value);
T get(T *value);
private:
int hash(T *data);
T _hashes[26]; //I want a fixed size here
};
template<class T>
HashMap<T>::HashMap()
{
for(int i = 0; i < 26; i++)
this->_hashes[i] = T();
}
template<class T>
HashMap<T>::~HashMap()
{
//Don't really have anything to delete here?
}
template<class T>
int HashMap<T>::hash(T *dat)
{
//Super simple, just to try things out
return (long int) dat % 26;
}
template<class T>
T HashMap<T>::get(T *val)
{
int idx = this->hash(val);
cout << idx << endl;
//Probably somewhere here i get my problem
if(this->_hashes[idx])
return this->_hashes[idx];
return T();
}
template<class T>
void HashMap<T>::add(T val)
{
//Should probably do some check if there's already an element here.
this->_hashes[this->hash(&val)] = val;
}
我遇到的问题是这编译得很好,但是当我在我的 main 中做这样的事情时.cpp:
HashMap<char> a = HashMap<char>();
a.add('h');
a.add('c');
a.add('g');
char *b = new char {'c'};
cout << a.get(b) << endl;
delete b;
它通常返回 id,即:
4
还有一个空行,只是一个空字符(函数的输出在 get(( 方法中(,但有时它会向我显示这样的东西:
18
g
而不是 18 和一个空行。我的问题是为什么会发生这种情况以及如何防止它?它是否与删除内存时没有"空"而是免费供其他程序使用有关,然后我没有正确初始化它?另外,如果您有时间,请指出任何错误或不太适合在代码中做事。
如果对我使用GCC Debian 4.4.5-8 编译和使用 g++ -g 文件编译和编译它.cpp -o 文件
感谢任何帮助!
您看到的行为是正常的:如果您get
放入哈希的值,它将由您的main
显示。给你令人惊讶的结果的是你的哈希函数:
return (long int) dat % 26;
这会对dat
指针进行哈希处理,而不是dat
指向的T
。尝试:
return *dat % 26;
(或者只使用标准std::set
。
代码的另一个问题:
T _hashes[26]; //I want a fixed size here (a
和
this->_hashes = new T[26]; (b
不兼容。要么使用固定数组 (a( 并且您不需要分配它 (b(,要么使用纯指针 ( T *_hashes
( 并执行 (b( - 我很惊讶您的编译器接受您拥有的东西。如果使用 (a( 则析构函数中不需要任何内容。如果使用 (b(,则需要在析构函数中delete []
。
在得到中传递一个T*
,但在集合中传递一个T
也有点奇怪。
下面是一个更惯用的 c++ 实现:
#include <array>
#include <iostream>
#define MAGIC_NUMBER 26 //rename this to something else preferably
template<class T>
class HashMap
{
public:
HashMap();
virtual ~HashMap(){};
void add(T value);
T get(T *value);//potentially confusing that add and get take different types
private:
int hash(T *data);
std::array<T, MAGIC_NUMBER> _hashes; //I want a fixed size here
};
template<class T>
HashMap<T>::HashMap()
{
std::fill(_hashes.begin(),_hashes.end(), T());
}
template<class T>
int HashMap<T>::hash(T *dat)
{
//Super simple, just to try things out
return (static_cast<int>(*dat)) % MAGIC_NUMBER;//prefer using c++ casts
}
template<class T>
T HashMap<T>::get(T *val) //this is strange, you pass in a pointer and get a non-pointer
{
int idx = this->hash(val);
std::cout << idx << std::endl;
if(this->_hashes[idx])
return this->_hashes[idx];
return T();
}
template<class T>
void HashMap<T>::add(T val)
{
//Should probably do some check if there's already an element here.
this->_hashes[this->hash(&val)] = val;
}
int main(void){
HashMap<char> a = HashMap<char>();
a.add('h');
a.add('c');
a.add('g');
char *b = new char {'c'};
std::cout << a.get(b) << std::endl;
delete b;
}
请注意,您需要使用 c++0x 或 c++11 功能进行编译,以获取 std::array 类的用法。数组类的主要优点之一是,与普通的 c 样式数组相比,内存分配的安全性更高。
现在,您可能需要重新考虑设计的某些元素。尤其令人困惑的是,add
和get
具有不同的类型。此外,这不是人们在听到hashmap时通常会想到的,这种结构更像是一个集合。
另外作为编码标准说明,如果您为成员变量添加前缀,则使用this->
来访问它们有点同义重复。
- 将字符串存储在c++中的稳定内存中
- C++ 指针的内存地址和指向数组的内存地址如何相同?
- Win32编译器选项和内存分配
- 当vector是tje全局变量时,c++中vector的内存管理
- 带内存和隔离功能的SQLite
- 是否可以通过C++扩展强制多个python进程共享同一内存
- 迭代时从向量和内存中删除对象
- 在C++中打印指向不同基元数据类型的指针的内存地址
- 这个指针和内存代码打印是什么?我不知道是打印垃圾还是如何打印我需要的值
- 在C++中对T*类型执行std::move的意外行为
- 多个文件的内存分配错误"在抛出 'std :: bad_alloc' what (): std :: bad_alloc 的实例后终止调用" [C++]
- 多线程程序中出现意外的内存泄漏
- 调试对父函数"belonging"内存的意外使用
- 带有标准容器和常量引用的c++代码显示出意外的内存
- C++意外的内存错误
- 内存仅在gcc上发生意外更改
- C++、内存和数组.创建我自己的练习哈希图.内存中留下的意外数据
- 发布版本工作意外-内存竞争和奇怪的QThread行为
- 尝试从xml文件训练CvANN_MLP ann时出现意外的内存错误
- 如果其中一个进程意外死亡,进程间内存会发生什么情况