2017-11-18 84 views
0

對於我正在實施散列映射的任務。我的valueOf()函數在main中返回垃圾,即使它找到了鍵的值並將其輸出到函數中。我找到了兩種可能的解決方案,但都不適合我的情況。C++模板基於指針的變量導致垃圾被返回,除非在之前存儲和輸出

類概述:

的HashTable

template <typename V> 
class HashTable { 
private: 
    string m_key; 
    V m_value; 
... 

MyStringMap

template <typename V> 
class MyStringMap : public AbstractStringMap<V> { 
private: 
    HashTable<V> * m_table; 
    int m_maxSize; 
    int m_currSize; 
    string EMPTY_KEY; 
    string TOMB_KEY; 
... 

而問題功能(這是在MyStringMap):

const V& valueOf(const string& key) const throw (Oops) { 
    int home; 
    int pos = home = hash(key); 

    // stops at found key (for success) or empty key (for failed) 
    for (int i = 1; (key != m_table[pos].getKey()) && (EMPTY_KEY != m_table[pos].getKey()); i++) 
     pos = (home + probe(key, i)) % m_maxSize; 

    // check found pos and return accordingly 
    if (key == m_table[pos].getKey()) { 
     return m_table[pos].getValue(); 
    } 
    else 
     throw Oops("Key Not Found!!"); 
} 

上面的return m_table[pos].getValue();部分在main中輸出時會返回垃圾,導致程序崩潰。但是,函數中有cout << "FOUND [" << m_table[pos].getKey() << "] [" << m_table[pos].getValue() << "]" << endl;(返回之前)會顯示正確的值。

我運行它主要的方式是:

try { 
    cout << "Person1? " << thelist.valueOf("Person1") << endl; 
    cout << "Person2? " << thelist.valueOf("Person2") << endl; 
} catch (Oops e) { 
    cout << e.getMsg() << endl; 
} 

兩個解決方案,我發現,但不適合有:

  • 追加c_str()到的結束主要功能,例如:cout << "Person1? " << thelist.valueOf("Person1").c_str() << endl;。由於我無法編輯main(如賦值指令),所以我不能使用它。
  • 返回一個變量,而不是直接的價值,並具有輸出它在那裏,例如:

V found = m_table[pos].getValue(); cout << "FOUND [" << m_table[pos].getKey() << "] [" << found << "]" << endl;

無論出於何種原因,這使得回報顯示正確的非垃圾值。但是,它是一個拙劣的解決方案,我不希望額外的輸出。


任何幫助,將不勝感激。我會在需要的地方澄清,因爲我確信這可能沒有意義。

+0

[mcve],請。山姆的回答下面有正確的可能性,但爲什麼猜測? – user4581301

回答

0

我猜你的getValue()方法返回一個V對象。該對象在堆棧上創建。然後您返回對該對象的引用。然後堆棧被你計算機中其他的東西覆蓋,你會得到垃圾。這也解釋了爲什麼返回一個對象的原理:它被分配在內存空間中並且不被覆蓋。

總之,您正在返回對堆棧中對象的引用。你不能這樣做,因爲你不知道在稍後閱讀時該地址會是什麼。

+0

那麼正確返回值的方法是什麼?將它分配給一個變量並返回該變量仍然會導致垃圾,除非我將.c_str()追加到main中的返回值。 – huhn