Почему аргумент типа карты C++ требует пустого конструктора при использовании []?


Смотрите также Стандартный список C++ и конструктивные типы по умолчанию

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

class MyClass
{
public:
    MyClass(MyType1 t);
    MyType2 &operator[](int index);
}

map<int, MyClass> myMap;

это дает мне следующую ошибку g++:

/usr / include/c++/4.3/bits / stl_map.h: 419: ошибка: нет соответствующей функции для вызова ' MyClass ()'

это компилируется нормально, если я добавить конструктор по умолчанию; я конечно, это не вызвано неправильным синтаксисом.

5 76

5 ответов:

эта проблема связана с оператором []. Цитата из документации SGI:

data_type& operator[](const key_type& k) - возвращает ссылку на объект что связано с конкретным ключ. Если карта уже не работает содержат такой объект,operator[] вставляет объект по умолчанию data_type().

если у вас нет конструктора по умолчанию, вы можете использовать вставка/функции. Следующий пример отлично работает:

myMap.insert( std::map< int, MyClass >::value_type ( 1, MyClass(1) ) );
myMap.find( 1 )->second;

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

без этого (и других требований) было бы бесполезно трудно реализовать различные внутренние операции копирования/перемещения/подкачки/сравнения в структурах данных, с которыми реализованы контейнеры STL.

при ссылке на стандарт C++, я вижу мой ответ был неточным. Default-конструкция, по сути, не является требованием:

от 20.1.4.1:

конструктор по умолчанию не требуемый. Определенный класс контейнера сигнатуры функций-членов указывают конструктор по умолчанию по умолчанию аргумент. T () должен быть четко определенным выражение...

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

реальные требования (23.1.3) из всех значений, хранящихся в контейнерах STL являются CopyConstructible и Assignable.

существуют также другие конкретные требования к конкретным контейнерам, такие как Comparable (например для ключей в карте).


кстати, следующие компиляции без ошибок на comeau:

#include <map>

class MyClass
{
public:
    MyClass(int t);
};

int main()
{
    std::map<int, MyClass> myMap;
}

так что это может быть g++ проблема.

проверьте требования сохраненного типа stl:: map. Многие коллекции stl требуют, чтобы сохраненный тип содержал некоторые определенные свойства (конструктор по умолчанию, конструктор копирования и т. д.).

конструктор без аргументов необходим STL:: map, потому что он используется, когда оператор[] вызывается с ключом, который еще не был сохранен картой. В этом случае оператор[] вставляет новую запись, состоящую из нового ключа и значения, построенного с помощью конструктора без параметров. И это новое значение возвращается.

проверьте, если:

  • вы забыли ';' после декларации класса.
  • MyType должен был быть объявлен соответствующим образом.
  • нет конструктора по умолчанию...

объявление std::map кажется правильным, я думаю.

скорее всего, потому что std::pair требует этого. std:: pair содержит два значения, используя семантику значений, поэтому вам нужно иметь возможность создавать их без параметров. Таким образом, код использует std::pair в разных местах для возврата значений карты вызывающему абоненту, и это обычно делается путем создания экземпляра пустой пары и присвоения ей значений перед возвратом локальной пары.

вы можете обойти это с помощью смарт-указателей, используя map > но это добавляет накладные расходы проверки на наличие нулевых указателей.