вставки в C ++ карту STL контейнер не удается - PullRequest
0 голосов
/ 12 апреля 2011

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

class compareByValue {                                                                             
  public:                                                                                          
    bool operator()(const string* s1, const string* s2) const                                      
    {                                                                                              
      if (s1 == s2)                                                                                
        return true;                                                                               
      if ((s1==NULL) || (s2==NULL))                                                                
        return false;                                                                              
      return (0 == s1->compare(s2->c_str()));                                                      
    }                                                                                                                                                                                             
}; 

map<string*, string*, compareByValue> nodeIdToIpAddress;

for (int i = 0; i < nrec; ++i) {
  nodeIdToIpAddress[ptr1[i]] = ptr2[i];                                              
  cout << "Added " << *(ptr1[i]) << " , " << *(ptr2[i]) << endl;
}

cout << "map has " << nodeIdToIpAddress.size() << " elements!" << endl;

У меня есть карта, которая содержит пары ключ-значение, которые являются указателями на строковые объекты.Я уверен, что ни ключи, ни значения не являются указателями NULL.Когда я запускаю вышеупомянутую программу (ну, я пропустил окружающий код, чтобы ее было легче понять), «Добавлено ... ...» печатается 49 раз.ptr1 [i], ptr2 [i] являются указателями на строковые объекты и не являются указателями NULL, потому что моя программа не выполняет segfault.говорит, что в карте есть только 1 элемент.

Буду признателен, если кто-нибудь подскажет мне, как найти исправление.Заранее спасибо.

РЕДАКТИРОВАТЬ: @Mark решение работало как очарование для меня.спасибо

РЕДАКТИРОВАТЬ 2: После просмотра ценных отзывов от @Mark и @James я думаю, что мне не нужно хранить указатели на строки на моей карте.Я собираюсь изменить свой код, чтобы хранить строки как ключи / значения, что означает, что мне не нужен специальный функтор компаратора.Большое спасибо.

Ответы [ 2 ]

6 голосов
/ 12 апреля 2011

Ваш компаратор неверен: if (s1 == s2) должен вернуть false, а компаратор должен произвести строгий слабый порядок .

[Что стоит, использование типа указателя в качестве ключа для std::map в лучшем случае необычно.]

2 голосов
/ 12 апреля 2011

Ваш оператор сравнения не прав. Пока вы можете предполагать, что никакие нули не добавлены, вы можете бросить, если обнаружите:

bool operator()(const string* s1, const string* s2) const                                      
{                                                                                              
  if (!s1 || !s2) throw std::runtime_error("Whatever");

  return *s1 < *s2;
}                                                                                 

РЕДАКТИРОВАТЬ: Я должен был бы более подробно остановиться на рассуждениях здесь. Операция сравнения, которую вы передаете в std::map (или set или sort, например), должна удовлетворять строгому слабому порядку. Это в основном означает, что x OP x равно false, если x OP y равно true, тогда y OP x равно false, и что x OP y, y OP z подразумевает x OP z (а также другие правила, касающиеся предметов это нельзя сравнивать).

Ваша функция не удовлетворяет этому несколькими способами: if (s1 == s2) необходимо вернуть false. if ((s1==NULL) || (s2==NULL)) не может вернуть false, потому что это будет означать, что null < anything и anything < null. Вам придется разделить его и вернуть true для s1 null и false для s2 null. return (0 == s1->compare(s2->c_str())); неверно, потому что это трехсторонний результат, а не < отношение.

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

Учитывая все вышесказанное, я бы настоятельно рекомендовал НЕ хранить строки по указателю в контейнерах, если у вас нет фактических доказательств того, что это узкое место в производительности. Более простую конструкцию легче поддерживать и поддерживать правильной, что приводит к улучшению программ в долгосрочной перспективе.

...