segmentation fault accessing a private class varia

2019-09-06 05:18发布

#define TABLE_SIZE 100489 // must be a power of 2
typedef map<string,int> MAP_TYPE;
typedef pair<string, int> PAIR_TYPE;

class HashTable
{
public:                                     //public functions
    HashTable();
    ~HashTable();
    int find(string);
    bool insert(string, int);
private:
    int hash( const char* );
    vector< MAP_TYPE > v;
};

//HashTable constructor
HashTable::HashTable()
{
    vector< MAP_TYPE > v;               //initialize vector of maps
    v.reserve(TABLE_SIZE);                  //reserve table size
    MAP_TYPE m;
    for (int i = 0; i < TABLE_SIZE; ++i)    //fill vector with empty maps
    v.push_back(m);
    cout << v.size();
}

int HashTable::find(string key)
{
    cout << "in find" << '\n';
    //String to const char* for hash function
    const char *c = key.c_str();
    //find bucket where key is located
    int hashValue = HashTable::hash(c);
    cout << hashValue << '\n';
    string s = key;
    cout << v.size(); //Prints 0 but should be TABLE_SIZE
    //look for key in map in bucket
    MAP_TYPE::const_iterator iter = v[hashValue].find(s);
    if ( iter != v[hashValue].end()) //check if find exists
        return iter->second; //return value of key
    else
        return -1; //arbitrary value signifying failure to find key
}

int main()
{
    HashTable my_hash;
    string s = "hi";
    int z = my_hash.find(s);
    cout << z; //should return -1
    return 0;
}

I'm testing out the find function my hash table but it is returning a segmentation fault. Even though I constructed vector v with the right size in the find function the size is now 0? I don't think it's accessing the same variable. The hash function is fine. What's wrong?

3条回答
迷人小祖宗
2楼-- · 2019-09-06 05:49

You have a local variable in the function called v as well as a private class member v.

try: this->v

查看更多
走好不送
3楼-- · 2019-09-06 06:04

In C++ class variables are best initialized in initialization lists:

HashTable::HashTable() : v(TABLE_SIZE, MAP_TYPE()) // **here**
{}

std::vector has a constructor that takes a size and a default value, so you can just call that. In fact, since the default value to use is actually a map created with the default constructor, you could actually just write the following, because the second parameter can be omitted in that case:

HashTable::HashTable() : v(TABLE_SIZE)
{}
查看更多
劫难
4楼-- · 2019-09-06 06:13

You're never actually inserting anything into the private member variable vector v. You create a vector as a local stack variable, which you also name v, in your HashTable constructor. You then proceed to insert items into that temporary vector, which goes out of scope as soon as you leave the constructor. So of course, later, in your HashTable::find function, the class member variable v is empty.

Your constructor should be something like:

//HashTable constructor
HashTable::HashTable()
{
    this->v.reserve(TABLE_SIZE);                  //reserve table size
    MAP_TYPE m;
    for (int i = 0; i < TABLE_SIZE; ++i)    //fill vector with empty maps
        this->v.push_back(m);
}

Above I use the this keyword to emphasize that I'm accessing the private member variable v, but you don't need it. (Although, generally it's good practice to adopt naming conventions for private member variables, such as adding a _ suffix or a m_ prefix or something.)

An even better way to initialize the vector would be to simply use the vector's fill constructor, as suggested in R. Martinho Fernandes's answer.

查看更多
登录 后发表回答