web-dev-qa-db-fra.com

Manière recommandée pour insérer des éléments dans la carte

Duplicate possible:
Dans les cartes STL, vaut-il mieux utiliser map :: insert que []?

Je me demandais, lorsque j'insère un élément dans la carte, quelle est la méthode recommandée. Devrais-je

map[key] = value;

ou

map.insert(std::pair<key_type, value_type>(key, value));

J'ai fait le test rapide suivant:

#include <map>
#include <string>
#include <iostream>

class Food {
public:
    Food(const std::string& name) : name(name) { std::cout << "constructor with string parameter" << std::endl; }
    Food(const Food& f) : name(f.name) { std::cout << "copy" << std::endl; }
    Food& operator=(const Food& f) { name = f.name; std::cout << "=" << std::endl; return *this; } 
    Food() { std::cout << "default" << std::endl; }
    std::string name;
};

int main() {
    std::map<std::string, Food> m0;

/*
1) constructor with string parameter
2) copy
3) copy
4) copy
*/
    m0.insert(std::pair<std::string, Food>("Key", Food("Ice Cream")));

/*
1) constructor with string parameter
2) default
3) copy
4) copy
5) =
*/
    // If we do not provide default constructor.
    // C2512: 'Food::Food' : no appropriate default constructor available
    m0["Key"] = Food("Ice Cream");
}
  1. Je réalise qu'en utilisant la fonction membre insert, l'appel de la fonction less value sera impliqué. Alors, est-ce que l'utilisation de insert est recommandée?
  2. Pourquoi le constructeur par défaut est nécessaire, alors que map[key] = value manière est utilisée?

Je sais que insert n’écrase pas la paire valeur/valeur d’existence, mais map[key] = value Est-ce que. Cependant, est-ce le seul facteur que je prenne en compte lorsque vous essayez de choisir entre les deux?

Que diriez-vous

  1. Performance
  2. Disponibilité du constructeur par défaut de la valeur
  3. ???
90
Cheok Yan Cheng
  1. insert n'est pas une méthode recommandée - c'est l'une des manières de l'insérer dans la carte. La différence avec operator[] est que le insert peut dire si l'élément est inséré dans la carte. De plus, si votre classe n'a pas de constructeur par défaut, vous êtes obligé d'utiliser insert.
  2. operator[] a besoin du constructeur par défaut car la carte vérifie si l'élément existe. Si ce n'est pas le cas, il en crée un en utilisant le constructeur par défaut et renvoie une référence (ou une référence const).

Etant donné que les conteneurs de carte n'autorisent pas les doublons, l'opération d'insertion vérifie pour chaque élément inséré s'il existe déjà un autre élément dans le conteneur avec la même valeur de clé. Si tel est le cas, l'élément n'est pas inséré et sa valeur mappée n'est pas modifiée. façon.

63
BЈовић

Utilisez insert si vous souhaitez insérer un nouvel élément. insert n'écrase pas un élément existant et vous pouvez vérifier qu'il n'y avait pas d'élément précédemment existant:

if ( !myMap.insert( std::make_pair( key, value ) ).second ) {
    //  Element already present...
}

Utilisation [] _ si vous souhaitez écraser un élément éventuellement existant:

myMap[ key ] = value;
assert( myMap.find( key )->second == value ); // post-condition

Ce formulaire remplacera toute entrée existante.

45
James Kanze

Citer:

Etant donné que les conteneurs de carte n'autorisent pas les doublons, l'opération d'insertion vérifie pour chaque élément inséré s'il existe déjà un autre élément dans le conteneur avec la même valeur de clé. Si tel est le cas, l'élément n'est pas inséré et sa valeur mappée n'est pas modifiée. façon.

Donc, insérer ne changera pas la valeur si la clé existe déjà, le [] operator Le fera.

MODIFIER:

Cela me rappelle une autre question récente: pourquoi utiliser at() au lieu de [] operator Pour récupérer les valeurs d'un vecteur. Apparemment, at() lève une exception si l'index est hors limites alors que [] operator Ne le fait pas. Dans ces situations, il est toujours préférable de consulter la documentation des fonctions car elles vous donneront tous les détails. Mais en général, il n'y a pas (ou du moins ne devrait pas être) deux fonctions/opérateurs qui font exactement la même chose.

Mon hypothèse est que, en interne, insert() vérifie d'abord l'entrée puis utilise lui-même le [] operator.

13
Luchian Grigore

map[key] = value est fourni pour une syntaxe plus simple. C'est plus facile à lire et à écrire.

La raison pour laquelle vous devez avoir un constructeur par défaut est que map[key] est évalué avant la cession. Si la clé n'était pas présente dans la carte, une nouvelle clé est créée (avec le constructeur par défaut) et sa référence est renvoyée à partir de operator[].

9
x13n