Вопрос:

Добавление объектов и пользовательские сравнения для std :: map <>

c++ std stdmap

32 просмотра

2 ответа

43698 Репутация автора

std::map<>Иногда мне кажется, что некоторые справочные материалы немного сложны для понимания.

  1. Когда я добавляю объект на карту, копирует ли он этот объект, как это CMap<>делает MFC ? Или он владеет объектом, который я добавил?

  2. Я пытаюсь создать пользовательский компаратор. Тем не менее, мой ключ является типом класса. Как мне указать, что компаратору должна быть передана ссылка на ключевой объект, а не на сам объект? Или будет достаточно объявления моего компаратора как получающего ссылку?

Автор: Jonathan Wood Источник Размещён: 11.08.2019 07:01

Ответы (2)


1 плюс

11 Репутация автора

Я не уверен, что полностью понимаю, что вы хотите знать, но позвольте мне поделиться своим опытом.

  1. если «Собственный объект» означает скопировать значение в собственное пространство памяти карты, это да. вставка одного элемента в std :: map , займет как минимум размер (пара ) памяти и автоматически уничтожит их при удалении. (игнорируя буфер распределения памяти stl)

    Если вы хотите «Ссылку», рассмотрите использование вместо этого std :: shared_ptr . Он занимает только одну область памяти и уничтожается, когда освобождаются все ссылки.

    PS: подробная карта памяти: Как я могу оценить использование памяти std :: map?

  2. Функция сравнения принимает эталонное значение, вы должны использовать это в большинстве случаев.

  3. пример

    class CObjectKey
    {
    public:
        CObjectKey(int type, int index)
            : type_(type), index_(index)
        {
        }
    
        bool operator <(const CObjectKey& right) const
        {
            if (this == &right)return false;
            return (type_ < right.type_) || (type_ == right.type_ && index_ < right.index_);
        }
    private:
        int type_;
        int index_;
    };
    
    int main()
    {
        std::map<CObjectKey, std::string> map1;
        map1.emplace(CObjectKey(1, 2), "val_1_2");
        map1.emplace(CObjectKey(1, 3), "val_1_3");
        std::cout << "Hello World! " << map1[CObjectKey(1,3)] << std::endl;
    }
    
    Автор: wwc Размещён: 11.08.2019 07:30

    0 плюса

    14428 Репутация автора

    Все объекты, содержащиеся в std::map(или любом другом стандартном контейнере) имеют время жизни, управляемое контейнером. Контейнеры содержат объекты. Если вы хотите, чтобы контейнер содержал указатели, вам нужно объявить его таковым.

    Например, в следующем коде

    struct MyType { /*...*/ };
    MyType my_object;
    std::map<int, MyType> my_map;
    my_map.insert({42, my_object});
    

    копия my_objectсделана, но в следующем

    struct MyType { /*...*/ };
    MyType my_object;
    std::map<int, MyType*> my_map;
    my_map.insert({42, &my_object});
    

    единственное , что получает скопирована это указатель на my_object, не my_objectсам по себе. В этом случае карта по-прежнему управляет временем жизни содержащихся в ней объектов, но эти содержащиеся объекты являются только указателями, и вы несете ответственность за то, чтобы указанные объекты пережили указатели на них. Лучший способ сделать это, как правило, использовать один из стандартных шаблонов классов интеллектуальных указателей: либо, std::unique_ptrлибо std::shared_ptr, в зависимости от ваших потребностей.


    Что касается второй части вашего вопроса, да, достаточно просто принять пользовательский компаратор для принятия значений по ссылке. std::mapпередает фактические объекты, содержащиеся в нем, компаратору.

    Автор: Miles Budnek Размещён: 11.08.2019 07:57
    Вопросы из категории :
    32x32