Почему аргумент типа карты C ++ требует использования пустого конструктора при использовании []? - PullRequest
81 голосов
/ 30 марта 2009

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

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

#include <map>

struct MyClass
{
    MyClass(int t);
};

int main() {
    std::map<int, MyClass> myMap;
    myMap[14] = MyClass(42);
}

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

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

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

Ответы [ 5 ]

141 голосов
/ 30 марта 2009

Эта проблема возникает с оператором []. Цитата из документации 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;
6 голосов
/ 30 марта 2009

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

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

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

от 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 ++.

2 голосов
/ 30 марта 2009

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

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

0 голосов
/ 30 марта 2009

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

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

0 голосов
/ 30 марта 2009

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

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

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

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