С++: использовать карту как значение другой карты

Мне просто интересно, могу ли я использовать «сложную» карту в качестве значения другой карты. Я самостоятельно определил несколько структур следующим образом:

typedef std::vector<std::string> pattern;
typedef std::map<int, std::vector<pattern>> dimPatternsMap;
typedef std::map<int, dimPatternsMap> supportDimMapMap;

Хорошо, позвольте мне объяснить эти вещи... pattern - это вектор строк. Для «меньшей» карты dimPatternsMap ключ представляет собой целое число, которое представляет собой размер шаблона (размер этого вектора, содержащего строки), а значение представляет собой вектор, содержащий шаблоны (который является вектором векторов...).

«Большая» карта supportDimMapMap также использует целое число в качестве значения ключа, но использует dimPatternsMap в качестве значения. Ключ означает «счетчик поддержки».

Теперь я начинаю строить эту «сложную» карту:

supportDimMapMap currReverseMap;
pattern p = getItFromSomePlace();  //I just omit the process I got pattern and its support
int support = getItFromSomePlaceToo();

if(currReverseMap.find(support) == currReverseMap.end()) {
    dimPatternsMap newDpm;

    std::vector<pattern> newPatterns;
    newPatterns.push_back(currPattern);
    newDpm[dim] = newPatterns;

    currReverseMap[support] = newDpm;

} else{
    dimPatternsMap currDpm = currReverseMap[support];

    if(currDpm.find(dim) == currDpm.end()) {
        std::vector<pattern> currDimPatterns;
        currDimPatterns.push_back(currPattern);

        currDpm[dim] = currDimPatterns;
    } else {
        currDpm[dim].push_back(currPattern);
    }
}

Простите, код действительно массовый...

Но тогда, когда я хочу пройти по карте, например:

for(supportDimMapMap::iterator iter = currReverseMap.begin(); iter != currReverseMap.end(); ++iter) {
        int support = iter->first;
        dimPatternsMap dpm = iter->second;

        for(dimPatternsMap::iterator ittt = dpm.begin(); ittt != dpm.end(); ++ittt) {
            int dim = ittt->first;
            std::vector<pattern> patterns = ittt->second;
            int s = patterns.size();
        }
}

Я обнаружил, что значение s всегда равно 1, что означает, что для каждого уникального значения поддержки и для каждого измерения этого значения поддержки существует только один шаблон! Но когда я отлаживаю свой код в процессе построения карты, я действительно обнаружил, что размер не равен 1 - я действительно успешно добавил новые шаблоны на карту... Но когда дело доходит до обхода, все размеры становятся равными 1, и я не не знаю почему...

Любые предложения или объяснения будут с благодарностью! Спасибо!!


person yvetterowe    schedule 02.11.2013    source источник
comment
На самом деле вам вообще не нужны вызовы find, поскольку operator[] будет создавать значение по умолчанию всякий раз, когда ключ новый, а контейнер, созданный по умолчанию, является пустым контейнером. Весь этот блок кода можно было бы переписать всего currReverseMap[support][dim].push_back(pattern);.   -  person aschepler    schedule 03.11.2013
comment
Я думаю, я должен сказать, что контейнер, сконструированный по умолчанию, обычно пуст. std::array<T,N> — яркий контрпример.   -  person aschepler    schedule 03.11.2013
comment
Я все еще не уверен, правильно ли я понимаю этот код, но я совершенно уверен, что в вашем выводе нет ничего плохого: насколько я могу судить, вы всегда добавляете вектор размера 1 на свою карту, поэтому ваши s всегда должны be 1 - ваш общий размер карты имеет больше элементов (хотя кажется, что вы даже ничего не добавляете в блок else), но в самом низу всегда должен быть размер 1   -  person UnholySheep    schedule 03.11.2013


Ответы (4)


dimPatternsMap currDpm = currReverseMap[support];

currDpm является копией currReverseMap[support]. Это не один и тот же объект. Итак, когда вы вносите изменения в currDpm, внутри currReverseMap ничего не меняется.

С другой стороны, если вы используете ссылку:

dimPatternsMap& currDpm = currReverseMap[support];

тогда currDpm и currReverseMap[support] действительно являются одним и тем же объектом, поэтому более поздние операторы, использующие currDpm, действительно будут изменять значение в пределах currReverseMap.

Есть несколько других мест, где ваш код также может быть полезен от ссылок.

person aschepler    schedule 02.11.2013

Мое предположение: вы должны использовать ссылку в своем else:

dimPatternsMap& currDpm = currReverseMap[support];

Ваш текущий код создает копию вместо использования исходной карты.

person thammi    schedule 02.11.2013

Ваша проблема в этой строке:

dimPatternsMap currDpm = currReverseMap[support];

Основываясь на коде, следующем за ним, он хочет читать так:

dimPatternsMap& currDpm = currReverseMap[support];

Без & вы изменяете копию записи, а не существующую запись.

person Dietmar Kühl    schedule 02.11.2013

Ваш код создает несколько копий объектов внизу, попробуйте использовать больше ссылок и итераторов (например, find() уже дает вам элемент, если он был найден).

Например, dimPatternsMap currDpm = currReverseMap[support]; фактически делает копию карты в вашей структуре и добавляет к ней элемент (не к оригиналу). Вместо этого попробуйте использовать ссылку.

person Luis    schedule 02.11.2013