2014-02-11 4 views
5

У меня есть два варианта создания std-карты. Я могу работать с обоими типами карт.std :: карта объектов или указателей объектов?

1. std::map<A, std::string>  
2. std::map<A*, std::string> 

где A является объектом класса

Позже в коде я должен выполнить операцию поиска.

1. std::map<A, std::string> myMap1; 
      if(myMap1.find(A_obj) != myMap1.end()) 
      { 
      } 

2. std::map<A*, std::string> myMap2; 
      if(myMap2.find(A_obj_ptr) != myMap2.end()) 
      { 
      } 

Я хочу знать, какой из них рекомендуется создать. В каком из этих двух вариантов я должен не должен перегружать всех операторов класса A для поиска работы. Какие из них будут иметь проблемы при работе вставки, если какие-либо операторы не будут перегружены.

Если это помогает, это класс А

class A 
{ 
    private: 
     std::vector<std::string> m_member; 

    public: 
     A(std::vector<std::string> input); 
}; 
+0

В зависимости от того, что представляет ваш объект. Для такого решения требуется дополнительная информация о 'A'. – Paranaix

+0

@Paranaix Я добавил класс 'A' info – ontherocks

+0

Также рассмотрите возможность использования (1) std :: unordered_map для более быстрого поиска времени (с учетом подходящей хеш-функции и, возможно, кэшированного хэша) или (2) отсортированного std :: vector > для лучшей локализации кэша. – metal

ответ

6

Обратите внимание, что эти два образца только функционально эквивалентны, если A экземпляры одиночек. В противном случае очень возможно, что два значения A, равные по значению, но разные по адресу. Это приведет к разной семантике.

Лично я предпочитаю версию std::map<A, std::string>, потому что ее семантика кристально чиста. Ключи имеют семантику равенства и нет потенциально для зависания или значения nullptr. В версии std::map<A*, std::string> есть множество вопросов, связанных с разработчиком, просматривающим код

  • Кому принадлежат ключевые значения?
  • Все ли случаи A одиночных чисел? Если нет, то как я могу гарантировать, что A, который я ищу, является значением A*, которое хранится?
  • Когда ключи освобождаются?
+3

Хорошие вопросы. Если следовать совету мудрецов Херба Саттера (http://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-parameters), необработанные указатели являются только несоблюждающими наблюдателями. Для владения можно использовать подходящий умный указатель (обычно, std :: unique_ptr для уникального владельца или std :: shared_ptr для совместного использования). – metal

+0

Вы правы. std :: map является более чистым. Но тогда мне придется перегружать операторов, таких как map :: key_comp, для поиска работы и другого оператора для работы вставки. Я прав? Не могли бы вы привести пример, что мне нужно сделать для вставки и поиска для работы в этом случае. – ontherocks

+1

@ontherocks, чтобы быть ключом в 'std :: map', должна существовать только допустимая реализация' std :: less '. Это может быть сделано с помощью специализированной специализации или добавления оператора '<' к типу – JaredPar

0

Первый вариант предпочтительнее. Для второго варианта нам нужно убедиться, что ключи (указатели здесь) защищены. Может быть, общие указатели помогут. Другая проблема заключается в том, что карта будет закорочена w.r.t. адрес объектов A, и это может быть не очень полезно. Ниже образец демонстрирует, как может быть определен компаратор, или может быть переопределен компаратор по умолчанию:

class A 
{ 
public: 
    int a; 
}; 

namespace std 
{ 
    template<> 
    struct less<A*> 
    { 
    bool operator()(const A* const a, const A* const b) const{ 
     return a->a < b->a; 

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