116 votes

Pourquoi l'argument de type de carte C ++ nécessite-t-il un constructeur vide lors de l'utilisation de []?

Voir aussi http://stackoverflow.com/questions/695372/c-standard-list-and-default-constructible-types

Pas un problème majeur, juste ennuyeux que je ne veux pas que ma classe à être instancié sans les arguments particuliers.

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

map<int, MyClass> myMap;

Cela me donne la suite de g++ erreur:

/usr/include/c++/4.3/bits/stl_map.h:419: error: no matching function for call to ‘MyClass()'

Cette compile très bien si j'ajoute un constructeur par défaut; je suis certain que ce n'est pas causée par une syntaxe incorrecte.

184voto

bayda Points 7454

Ce problème vient avec l'opérateur []. Extrait de la documentation SGI:

data_type& operator[](const key_type& k) - Renvoie une référence à l'objet associé à une clé particulière. Si la carte ne contient pas déjà un tel objet, operator[] insère l'objet par défaut data_type() .

Si vous n'avez pas de constructeur par défaut, vous pouvez utiliser des fonctions insert / find. L'exemple suivant fonctionnera:

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

7voto

Assaf Lavie Points 20181

Oui. Les valeurs dans des conteneurs STL nécessité de maintenir la sémantique de copie. OIE, il faut qu'ils se comportent comme des types primitifs (ex int), ce qui signifie, entre autres choses, ils doivent être par défaut constructible.

Sans cela (et d'autres exigences), il serait inutilement difficile à mettre en œuvre les différents interne copier/déplacer/swap/comparer les opérations sur les structures de données avec laquelle les conteneurs STL sont mis en œuvre.

Lors de la référence à la Norme C++, je vois que ma réponse n'était pas exacte. Par défaut-la construction est, en fait, pas une obligation:

De 20.1.4.1:

Le constructeur par défaut n'est pas nécessaire. Certaines classe de conteneur membre des signatures de fonction spécifier l' constructeur par défaut comme valeur par défaut argument. T() doit être bien défini expression ...

Donc, à strictement parler, de votre type de valeur ne doit être par défaut constructible si vous arrive d'être en utilisant une fonction de contenant qui utilise le constructeur par défaut dans sa signature.

Les besoins réels (23.1.3) à partir de toutes les valeurs stockées dans des conteneurs STL sont CopyConstructible et Assignable.

Il y a aussi d'autres exigences spécifiques pour notamment les conteneurs ainsi, comme Comparable (par exemple pour les clés dans un plan).


D'ailleurs, la suite se compile sans erreur sur comeau:

#include <map>

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

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

Donc cela pourrait être un g++ problème.

5voto

oo_olo_oo Points 1139

Exigences en matière de vérification de l'stockés type de la stl::map. De nombreux stl collection exiger que stockées type contient certaines propriétés spécifiques (par défaut constructeur, constructeur de copie, etc.).

Constructeur sans arguments est nécessaire par la stl::map, parce qu'il est utilisé, lorsque l'opérateur[] est appelé avec la clé, ce qui n'a pas déjà été conservé par la carte. Dans ce cas, l'opérateur[] insère la nouvelle entrée composé de la nouvelle clé et la valeur construite à l'aide de constructeur sans paramètre. Et cette nouvelle valeur est alors retourné.

-2voto

jmucchiello Points 10521

Probablement parce que std::pair exige. std::pair a deux valeurs à l'aide de la valeur sémantique de sorte que vous devez être en mesure de les instancier sans paramètres. Si le code utilise des std::pair dans différents lieux pour retourner les valeurs de la carte de l'appelant et cela se fait couramment par l'instanciation d'un vide de la paire et de l'affectation de valeurs en avant de retourner le local paire.

Vous pourriez obtenir autour de cette avec des pointeurs intelligents à l'aide d'une map<int, smartptr<Maclasse> > mais qui ajoute les frais généraux de la vérification des pointeurs null.

-2voto

Hernán Points 2452

Vérifier si:

  • Vous avez oublié le ';' après la déclaration de classe.
  • Mon type aurait dû être déclaré en conséquence.
  • Aucun constructeur par défaut là-bas ...

La déclaration std :: map semble correcte, je pense.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X