114 votes

Méthode recommandée pour insérer des éléments dans une carte

Duplicata possible :
Dans les cartes STL, est-il préférable d'utiliser map::insert plutôt que [] ?

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

map[key] = value;

o

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

J'ai effectué 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 à la fonction de la valeur sera moins important. Ainsi, l'utilisation de insert une méthode recommandée ?
  2. Pourquoi un constructeur par défaut est-il nécessaire lorsque map[key] = value est utilisée ?

Je sais que insert n'écrase pas la paire clé/valeur de l'existence, mais map[key] = value fait. Cependant, est-ce le seul facteur que je prenne en considération lorsque j'essaie de choisir entre les deux ?

Pourquoi pas

  1. Performance
  2. Disponibilité du constructeur par défaut de la valeur
  3. ? ??

85voto

BЈовић Points 28674
  1. insert n'est pas une méthode recommandée - c'est l'une des méthodes d'insertion dans la carte. La différence avec operator[] est que la insert permet de savoir 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 à l'aide du constructeur par défaut et renvoie une référence (ou une référence constante).

Les conteneurs de cartes n'autorisant pas la duplication des valeurs clés, l'opération d'insertion vérifie pour chaque élément inséré si un autre élément existe déjà dans le conteneur avec la même valeur clé ; si tel est le cas, l'élément n'est pas inséré et sa valeur mappée n'est modifiée en aucune manière.

55voto

James Kanze Points 96599

Utilisation insert si vous souhaitez insérer un nouvel élément. insert ne sera pas écraser un élément existant, et vous pouvez vérifier qu'il n'y avait pas d'élément existant précédemment. n'existait pas auparavant :

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.

13voto

Luchian Grigore Points 136646

Je cite :

Les conteneurs de cartes n'autorisant pas la duplication des valeurs clés, l'opération d'insertion vérifie pour chaque élément inséré si un autre élément existe déjà dans le conteneur avec la même valeur clé ; si tel est le cas, l'élément n'est pas inséré et sa valeur mappée n'est modifiée en aucune manière.

Ainsi, l'insertion ne modifiera pas la valeur si la clé existe déjà. [] operator volonté.

EDIT :

Cela me rappelle une autre question récente : pourquoi utiliser le système d'information de l'Union européenne ? at() au lieu de la [] operator pour extraire des 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, qui vous donnera tous les détails. Mais en général, il n'y a pas (ou du moins il ne devrait pas y avoir) deux fonctions/opérateurs qui font exactement la même chose.

Je pense que c'est le cas en interne, insert() vérifiera d'abord la présence de l'entrée et utilisera ensuite lui-même la fonction [] operator .

11voto

x13n Points 1909

map[key] = value est fourni pour faciliter la syntaxe. Il est plus facile à lire et à écrire.

La raison pour laquelle il est nécessaire d'avoir un constructeur par défaut est que map[key] est évaluée avant l'affectation. Si la clé n'était pas présente dans la carte, une nouvelle carte est créée (avec le constructeur par défaut) et la référence à celle-ci est renvoyée par la fonction operator[] .

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