Considérez le code suivant:
std::map<std::string, int> m1; auto i = m1.find("foo"); const char* key = ... auto j = m1.find(key);
5 Réponses :
Ne pas utiliser les pointeurs; Au lieu de cela, passez directement des chaînes. Ensuite, vous pouvez profiter des références:
void do_something(std::string const & key) { auto it = m.find(key); // .... }
... sauf si vous n'avez pas besoin d'écrire C. mais alors .. Pourquoi avez-vous besoin de C ++? :-RÉ
Bien que cela ne traite pas de M1.Find ("FOO") CODE> Création d'un problème d'objet temporaire (même si, finalement, ce temporaire ne peut pas être contourné).
Je ne peux pas éviter d'utiliser des pointeurs. Je recherche une valeur qui provient de la source externe en tant que chaîne C. Cela signifie toujours que je dois construire une chaîne à chaque recherche.
@ Andrécaron: Pourquoi auriez-vous jamais besoin de trouver un littéral à chaîne? Dans ce cas, il suffit de faire une constante globale std :: string const foo_string ("foo") code> et utilisez-le ...
@ALEXB: interfaces propres. Faites la chaîne une fois à la limite de la bibliothèque externe, puis réutilisez cette chaîne. Vous n'avez pas de question pure c ++, donc c'est un peu trompeur.
@Kerreksb Il y a une nouvelle chaîne est à chaque fois. Considérez-le comme un grand flux d'entre eux. La recherche n'est faite qu'une fois, lorsque je tire une nouvelle chaîne de ce "flux".
@Kerreksb: Peu importe pourquoi quelqu'un voudrait faire cela (bien que moins de taper se vienne à l'esprit). Peut-être que votre réponse devrait prendre le formulaire "Vous ne pouvez pas contourner le temporaire, mais en faisant ... vous pouvez vraiment atténuer le coût de la création d'un std :: string code> instance". Ceci bien sûr, sortez la fenêtre après le dernier commentaire d'Alex.
Eh bien, Pour la première partie du code, vous pouvez avoir une STD statique constante :: String avec valeur "FOO" à la recherche. De cette façon, vous ne créerez pas de copies. P>
Si vous souhaitez aller voir SPARTAN, vous pouvez toujours créer votre propre type pouvant être utilisé comme une chaîne, mais peut également contenir le pointeur sur les littéraux de chaîne. P>
Mais en tout état de cause, les frais généraux associés à la recherche de cartes sont si énormes, donc cela n'a pas vraiment de sens. Si j'étais vous, je voudrais d'abord remplacer la carte / unommod_map avec le hachage dense de Google. Ensuite, je dirigerais Vtutune d'Intel (amplificateur ces jours-ci) et je verrais où le temps allait et optimise ces endroits. Je doute des chaînes que les clés apparaîtront dans une liste des dix top dix. P> Recherche code> accepte réellement une référence constante à la touche, de sorte que vous ne pouvez pas éviter de le créer à un point ou un autre. P>
Je dois manquer quelque chose, mais qui est Spartan?
@Cameron: Je crois qu'il est l'auteur du compilateur Cegean C. Très frugal et industrieux.
Regardez le stringref classe de LLVM. P>
Ils peuvent être construits très pas chers à partir de C-Strings, littéraux à cordes ou STD :: String. Si vous avez créé une carte de ceux-ci, au lieu de STD :: String, la construction serait très rapide. P>
C'est un système très fragile cependant. Vous devez être sûr que quelle que soit la source des chaînes que vous insérez des séjours vivants et non modifiés pour la durée de vie de la carte. P>
Vous pouvez éviter le temporaire en donnant le Ainsi, quelque chose comme: P> std :: map code> une classe de comparaison personnalisée, qui peut comparer
char * code> s. (La valeur par défaut utilisera l'adresse du pointeur, qui n'est pas ce que vous voulez. Vous devez comparer la valeur de la chaîne.)
class StrCmp
{
public:
bool operator () (const char *a, const char *b)
{
return strcmp(a, b) < 0;
}
};
// Later:
std::map<const char *, int, StrCmp> m;
Au Downvoter: l'esprit expliquant votre bowvote?
Vos mots sonnent comme le comparateur personnalisé fonctionne avec std :: map
Il n'y a aucun moyen d'éviter une instance temporaire Si vous n'avez besoin que d'un très < / em> petit sous-ensemble de la fonctionnalité de chaîne (par exemple, une seule affectation et des copies), vous pouvez alors écrire une petite classe de chaîne à usage spécial qui stocke un pointeur alors, vous pouvez utiliser cette classe comme suit: p> notes strong>: Si votre implémentation n'utilise pas l'optimisation de la valeur de retour, vous souhaitez trouver une autre syntaxe de la méthode code> proxy code>, telle qu'un constructeur avec une surcharge spéciale ( Prendre une personnalisation std :: string code> qui copie les données de caractères. Notez que ce coût est très faible et n'aboutit pas une allocation de mémoire dynamique si votre implémentation de la bibliothèque standard utilise des optimisations de chaîne courtes. Toutefois, si vous avez besoin de chaînes de style C proxy sur une base fréquente, vous pouvez toujours trouver personnalisé Des solutions qui passent par-réussir cette allocation. Cela peut payer si vous devez faire cela vraiment em> souvent et vos chaînes sont suffisamment longues pour ne pas bénéficier des optimisations de chaîne courtes. P>
Const Char * code> et une fonction pour libérer la mémoire. < / p>
pas cher_string code> instance Ne pas créer une copie du tampon de caractères comme
std :: string code> fait, mais il conserve une sémantique de copie sûre pour stocker des instances de
pas cher_string code> dans des conteneurs standard. P>
proxy_t code> type à la
std :: Nothrow c Ode> pour le placement nouveau). P> p>
... Mais par votre définition de cheap_string code>, ne tenterait-il pas de (incorrectement) gratuit
"foo" code> une fois que le temporaire a été supprimé?
Non, parce que la méthode proxy () code> utilise le Deleter personnalisé
Abandon () code> qui est un non-OP qui n'appelle jamais SUPPRE. Laissez-moi élaborer.
Si vous pouviez modifier la définition de la carte, vous pouvez utiliser un comparateur personnalisé qui permet
Char Cons * code> directement
Où obtiendriez-vous un
const char * code>?
@Pablo: Mais alors .. Quelqu'un devra gérer une mémoire où ces clés pointeront. Sauf si elles sont toutes dans le segment de données ...
@Pablo Oui et vous devrez gérer vous-même des chaînes brutes sur le tas. C'est là que je suis en ce moment. Je veux me débarrasser autant de code personnalisé que possible sans sacrifier la performance.
Je ne voulais pas modifier la définition de la carte pour contenir
Char Const * code>, je voulais modifier le comparateur pour autoriser stocker
std :: string code> et comparer avec
Char Cons * Code> sans créer de
STD :: String Code>
Nevermind .. comme @vladlazarenko a déclaré ci-dessous, vous trouverez une touche code> de toute façon, le comparateur personnalisé ne verra même pas l'argument original
chartons * code>.
C ++ 14 introduit des «comparateurs transparents» pour permettre des opérations de comparaison hétérogènes, par ex. entre
std :: string code> et un pointeur de caractère.