stl :: map erase vs std :: vector erase ведут себя по-разному - PullRequest
3 голосов
/ 11 августа 2011
 class CSensor
 {
    public:
    CSensor(int nVal1,char* pVal2,unsigned int nVal3);
    CSensor(const CSensor& refMessage);
    const CSensor& operator=(const CSensor& refMessage);
   ~CSensor(void);
   private:
   int m_nVal1;
   char* m_pVal2;   
   unsigned int m_nVal3;
 };

 // vector erase

 std::vector<CSensor> SensorList;
 CSensor obj1(1,"Test1",10);
 SensorList.push_back(obj1);
 CSensor obj2(2,"Test2",11);
 SensorList.push_back(obj2);
 CSensor obj3(3,"Test3",12);
 SensorList.push_back(obj3);

 SensorList.erase (SensorList.begin()+1);



// map erase
    std::map<int ,CSensor> ListSensor;
CSensor obj11(1,"Test1",10);    
CSensor obj12(2,"Test2",11);
CSensor obj13(3,"Test3",12);

ListSensor.insert(std::pair<int,CSensor>(1,obj11));
ListSensor.insert(std::pair<int,CSensor>(2,obj12));
ListSensor.insert(std::pair<int,CSensor>(3,obj13));

ListSensor.erase(2);

Я отлаживал оба случая. В обоих случаях я удаляю второй элемент. В случае вектора он копирует 3 элемента во 2-е ядро ​​и затем удаляет 3-е место.

Так что, когда ты говоришь

   List.erase (List.begin()+1);

это вызов оператора присваивания (CSensor =), а затем вызов деструктора.

В случае карты, когда я делаю

   ListSensor.erase(2);

он вызывает только деструктор.

Я прошел Вектор STL против стирания карты . Он говорит Итератор, не может объяснить поведение.

У меня вопрос, почему стирание ведет себя по-разному для этих двух контейнеров STL ??

Ответы [ 2 ]

5 голосов
/ 11 августа 2011

Это не поведение .erase само по себе , а следствие того, как работает каждый соответствующий контейнер.

Удаление из вектора

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

Обычно это делается путем копирования (или перемещения) элементов с последующим обрезанием остатка:

  • Векторные элементы в памяти:

    +---+---+---+---+---+---+---+---+---+
    | a | b | c | d | e | f | g | h | i |
    +---+---+---+---+---+---+---+---+---+
    
  • Стереть 'e':

    +---+---+---+---+---+---+---+---+---+
    | a | b | c | d |   | f | g | h | i |
    +---+---+---+---+---+---+---+---+---+
    
  • Заполните пробел, копируя / перемещая:

                       <--
    +---+---+---+---+---+---+---+---+---+
    | a | b | c | d | f | f | g | h | i |
    +---+---+---+---+---+---+---+---+---+
    
                           <--
    +---+---+---+---+---+---+---+---+---+
    | a | b | c | d | f | g | g | h | i |
    +---+---+---+---+---+---+---+---+---+
    
                               <--
    +---+---+---+---+---+---+---+---+---+
    | a | b | c | d | f | g | h | h | i |
    +---+---+---+---+---+---+---+---+---+
    
                                   <--
    +---+---+---+---+---+---+---+---+---+
    | a | b | c | d | f | g | h | i | i |
    +---+---+---+---+---+---+---+---+---+
    
  • Изменить размер контейнера:

    +---+---+---+---+---+---+---+---+
    | a | b | c | d | f | g | h | i |
    +---+---+---+---+---+---+---+---+
    

Удаление с карты

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

3 голосов
/ 11 августа 2011

Это одна из причин иметь разные контейнеры!

Вектор должен копировать элементы, следующие за ослабленным элементом, чтобы закрыть оставленную им «дыру». В противном случае элементы больше не будут смежными.

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

В защиту вектора: копирование пары элементов может быть дешевле, чем выделение отдельных узлов дерева и поддержание баланса дерева. Всегда есть компромиссы!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...