2015-05-02 2 views
0

Я пытаюсь использовать следующий основной тест для выбранного класса HashMap.push_back в вектор внутри класса хэш-карты

#include <iostream> 
#include "HashMap.h" 

using namespace std; 

int main(){ 
    HashMap<int,vector<string>> hash(20); 
    vector<string> vec; 

    cout<<"Inserting item... "; 
    if(hash.insert(2)){ 
     cout<<"successful. "; 
     hash.find(2).push_back("word "); 
     hash.find(2).push_back("is "); 
     hash.find(2).push_back("pushed "); 
     hash.find(2).push_back("back. "); 
     hash.find(2).push_back("yes!\n"); 
    } else { 
     cout<<" unsuccessful."; 
     return 0; 
    } 
    vec = hash.find(2); 

    for(auto& words: vec) 
     cout<< words<<endl;; 

    return 0; 
} 

Заключительный цикл не печатает ничего.

find функция определяется следующим образом:

Data find(const Key& key) { return array[findPos(key)].data_; } 

где Data является второй переменной шаблона в классе HashMap. Я провел пару тестов, и find возвращает пустые векторы, даже после использования push_back. почему это? что я могу сделать, чтобы вставлять элементы в векторы?

ответ

1

Проблема заключается в том, что ваша функция find возвращает копию значения внутри вашей структуры данных. В частности,

Data find(const Key& key) { return array[findPos(key)].data_; } 

возвращает значение Data, который должен сказать, что копии компилятора значение в операторе возврата к локальной переменной для вызова функции. I., каждый вызов hash.find(2) дает новую копию пустого вектора. Затем вы модифицируете только что созданный пустой вектор. После того, как заканчивается push_back, вектор разрушается, так как отсутствует lvalue, к которому он привязан; это временно.

Внесение изменений в функцию:

Data& find(const Key& key) { return array[findPos(key)].data_; } 

будет сделать то, что вы хотите, так как он будет возвращать ссылку внутренней структуры данных. Обратите внимание, что с этим связаны некоторые связанные с этим опасности. Это затрудняет обнаружение одновременного доступа, позволяет пользователям получать ссылки, которые могут быть признаны недействительными (например, если вы изменяете размер array) и обычно нарушает инкапсуляцию. Тем не менее, это путь, если вы делаете хэш-карту с изменяемыми значениями.

+0

О, ничего себе, я полностью замаскировал это. Спасибо большое! – zeta

+0

как я могу сделать так, чтобы ссылки не становились недействительными? – zeta

+0

Вам нужно будет создать свой собственный тип итератора, который сохранит (общий) указатель на исходный объект - это позволит вам получить доступ к массиву после перераспределения. Это нетривиально, медленнее и, вероятно, не нужно делать, хотя, поскольку вы можете просто потребовать (как это делает стандарт), что ссылки используются только до следующей вставки. – VF1

Смежные вопросы