Нужна помощь в понимании использования карты C ++ в качестве ассоциативного массива - PullRequest
6 голосов
/ 18 ноября 2009

Я просматривал «Использование Карт в качестве ассоциативных массивов» Джозуттиса (из Стандартная библиотека C ++ - Учебное пособие и справочник, 2-е издание ) и наткнулся на Использование std :: map в качестве ассоциативный массив при переполнении стека. Теперь у меня есть еще вопросы по конструкторам, которые вызываются при вставке в карту.

Вот мой пример программы (не использует лучшие практики кодирования; прошу прощения за это):

class C
{
public:

   string s;

   C() { cout << "default " << endl;}

   C(const string& p) : s(p)
   { cout << "one param" << endl;}

   C(const C& obj)
   {
       if (this != &obj)
       {
         s = obj.s;
       }
       cout << "copy constr" << endl;
   }

   C& operator  = (const C& obj)
   {
       if (this != &obj)
       {
             s = obj.s;
       }
      cout << "copy initializer" << endl;
      return *this;
   }
};

int main()
{
    map<int,C> map1;
    C obj("test");

    cout << "Inserting using index" << endl;
    map1[1] = obj;

    cout << "Inserting using insert / pair" << endl;
    map1.insert(make_pair(2,obj));
}

Выходные данные для этой программы:

one param
Inserting using index
default
copy constr
copy constr
copy initializer
Inserting using insert / pair
copy constr
copy constr
copy constr
copy constr

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

Но выполнение map1[1] = obj создает следующий вывод;

Inserting using index
default
copy constr
copy constr
copy initializer

Может кто-нибудь помочь мне лучше понять инициализацию?

Ответы [ 4 ]

8 голосов
/ 18 ноября 2009

Если вы читаете спецификацию для std :: map, он говорит, что operator [] эквивалентен (в данном случае)

(*((this->insert(make_pair(1,C()))).first)).second

Так что это объясняет все вызовы конструктора, которые вы видите. Сначала он вызывает конструктор по умолчанию C (). Затем он вызывает make_pair, которая копирует объект C. Затем он вызывает insert, который создает копию только что созданного парного объекта, снова вызывая конструктор C copy. Наконец, он вызывает оператор присваивания, чтобы установить для вставленного объекта тот, которому вы его назначаете.

2 голосов
/ 18 ноября 2009

Не знаю. Но это интересно:

#include <string>
#include <map>
#include <iostream>
using namespace std;

class C
{
    public:
        string s;
        C()
        {
            cout << "default " << endl;
        }
        C(const string& p)
        : s(p)
        {
            cout << "one param(" << s << ")" << endl;
        }
        C(const C& obj)
            :s(obj.s)
        {
           cout << "copy constr(" << s << ")" <<endl;
        }
        C& operator  = (const C& obj)
        {
            cout << "copy initializer\t" <<;

            C copy(obj);
            std::swap(s,copy.s);

            return *this;
        }
};

int main()
{
    map<int,C> map1;
    cout << "Inserting using index" << endl;
    map1[1] = C("Plop");
}

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

Inserting using index
default
copy constr()
copy constr()
one param(Plop)
copy initializer      copy constr(Plop)
0 голосов
/ 18 ноября 2009

На самом деле map1[1] = obj создаст pair первый

0 голосов
/ 18 ноября 2009

Что произойдет, если вы просто выполните map[1];? Это может включать внутренние копии, в зависимости от реализации map, которую использует ваша стандартная библиотека.

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