C++: value_type contre make_pair, qui est plus rapide pour la carte insérer?
typedef map<KeyType, ValType> KVMap;
KVMap kvmap;
kvmap.insert( KVMap::value_type( key, val ) );
kvmap.insert( make_pair( key, val ) );
Laquelle des options ci-dessus pour l'insérer à un STL carte est toujours plus rapide? Pourquoi?
Note: je suis bien conscient que insert()
est plus rapide que l'utilisation []=
pour l'ajout (mise à jour) des paires clé-valeur d'une carte. Veuillez supposer que ma question est à propos de l'ajout, pas de mise à jour. Donc j'ai limité à insert()
.
- À moins que votre programme se compose uniquement d'inserts pour cartes, pensez-vous vraiment aucune différence de vitesse sera perceptible? Vous devriez obtenir un profil de profil de votre produit fini, propre, maintenable programme pour voir ce que la lenteur des spots sont en réalité. Et il ne devrait pas y avoir une différence, après l'in-lining.
- GMan: La différence était minuscule. Voir mon commentaire à la manière de Karl réponse.
Vous devez vous connecter pour publier un commentaire.
Des Chances que le premier sera 'epsilon-rapide, à cause de cela (à partir de 23.3.1 dans la norme) :
Dans la première version, vous avez directement la construction du type approprié prévu par
std::map<K,V>::insert
Dans la deuxième version, une conversion à l'aide de
std::pair
modèle constructeur est impliqué. En effet,std::make_pair
sera plus susceptible de déduire de ses arguments de modèle àKeyType
etValType
, renvoyant ainsi unestd::pair<KeyType, ValType>
.Cela ne correspond pas au type de paramètre de
std::map<K,V>::insert
, qui eststd::pair<const KeyType, ValType>
(la différence étant leconst
qualifiés de la première). Lestd::pair
conversion constructeur est utilisé pour créer unstd::pair<const K, V>
de lastd::pair<K, V>
.Pour être juste, je ne crois pas que vous pouvez même mesurer la différence (et je ne suis même pas sûr que les compilateurs génèrent un code différent pour ces).
Il y a en fait un argument pour
value_type
surmake_pair
. C'est parce que, pour diverses arcanes raisons,make_pair
accepte ses arguments par valeur. D'autre part,value_type
, un alias pourstd::pair<const Key, value>
, aura son constructeur appelé avec les arguments passés par référence const. Il y a un risque de perte d'efficacité de la passe-par-valeur enmake_pair
contre passé par référence, qui pourrait, en théorie, avoir un impact notable sur votre programme.Un autre problème à être inquiet avec
make_pair
est quemake_pair
généralement de créer une paire de typestd::pair<Key, Value>
par rapport à lastd::pair<const Key, Value>
nécessaire à l'intérieur de lamap
. Cela signifie qu'il pourrait y avoir une autre copie superflue étant faite, cette fois de lapair
pour obtenir la conversion fonctionne correctement.En bref, à l'aide
make_pair
peut provoquer deux complètement inutile copies de la clé et la valeur sont prises, tout en utilisant lavalue_type
constructeur n'en a aucun.C'est juste une supplémentation.
insert( make_pair(...) )
les appels de constructeur de copie 4 fois théoriquement raison de la raison que d'autres
answerers mentionné.
insert( value_type(...) )
les appels de constructeur de copie 2 fois.
operator[]
les appels de constructeur par défaut une fois et constructeur de copie 2 fois
dans un cadre typique de la mise en œuvre.
constructeur par défaut est appelé à l'intérieur
operator[]
pourinsert( value_type( ..., mapped_type() ) )
.constructeur de copie est appelé une fois pour la copie
insert()
'argument(pair
),et une fois de copier-construire un noeud interne de la carte.
Donc, si vous utilisez
insert
avecmake_pair
,il ne peut pas être dit que
insert
est toujours plus rapide queoperator[]
même pour l'ajout.Probablement, cela dépend de la situation.
Comme vous le savez peut-être, au vu de ce qui précède,
emplace
a été proposé pour la nouvellestandard.
Ils sont fondamentalement la même chose.
KVMap::value_type
est un typedef pourstd::pair<KeyType, ValType>
, de sorte que c'est juste d'appeler le constructeur.std::make_pair
est un modèle de fonction qui appelle simplement le constructeur (elle existe parce que les types de modèles peuvent être déduites pour les fonctions libres, mais pas pour les constructeurs). Une fois que tous les incroyablement standard optimisations sont faites, il n'y a pas de raison pour qu'il y ait une différence.Je ne sais pas comment vous faites des tests, mais il y a beaucoup, beaucoup de manières de faire que le mal.
Comme pour
insert()
contre l'attribution paroperator[]
, ce dernier doit faire plus de travail sur le plan conceptuel (lorsque vous ajoutez un nouvel élément de cette façon, il est supposé par défaut-la construction d'un élément, et ensuite affecter plus haut), mais en fonction de laValType
, il pourrait être optimisé en basiquement la même chose de nouveau.