web-dev-qa-db-fra.com

Ajouter int à std :: string

J'ai essayé deux façons différentes d'ajouter un int à un std::string et à ma grande surprise, j'ai obtenu des résultats différents:

#include <string>

int main()
{
    std::string s;
    s += 2;     // compiles correctly
    s = s + 2;  // compiler error

    return 0;
}

Pourquoi compile-t-il et fonctionne-t-il correctement lorsque j'utilise le += opérateur, mais échoue lorsque j'utilise le + opérateur?

Je ne pense pas que la question soit comme comment concaténer un std :: string et un int?

Dans cette question, aucune réponse n'utilise += opérateur.Et la différence entre += et + _ opérateur de std::string est la clé pour résoudre mon doute.

Franchement, la question est un bon exemple pour expliquer pourquoi c ++ est si difficile à maîtriser.

37
navylover

TL; DR operator+= Est une fonction membre de la classe dans class string, Tandis que operator+ Est un modèle. une fonction.

La classe standard template<typename CharT> basic_string<CharT> A surchargé la fonction basic_string& operator+=(CharT) et la chaîne est simplement basic_string<char>.

Comme les valeurs qui correspondent à un type inférieur peuvent être automatiquement transtypées dans ce type, dans l'expression s += 2, Le 2 est pas traité comme int, mais char à la place. Il a exactement le même effet que s += '\x02'. Un caractère avec ASCII code 2 (STX) est ajouté, et non le caractère '2' (avec ASCII valeur 50 ou 0x32).

Cependant, string n'a pas de fonction membre surchargée comme string operator+(int), s + 2 N'étant pas une expression valide, une erreur est générée lors de la compilation. (Plus ci-dessous)

Vous pouvez utiliser operator + function dans une chaîne de la manière suivante:

s = s + char(2); // or (char)2
s = s + std::string(2);
s = s + std::to_string(2); // C++11 and above only

Pour les personnes soucieuses de savoir pourquoi 2 n'est pas automatiquement converti en char avec operator+,

template <typename CharT>
  basic_string<CharT>
  operator+(const basic_string<CharT>& lhs, CharT rhs);

Ce qui précède est le prototype[Remarque] pour l'opérateur plus dans s + 2, et comme il s'agit d'une fonction modèle, il nécessite une implémentation de operator+<char> et de operator+<int>, ce qui est en conflit. Pour plus de détails, voir Pourquoi le downcasting automatique n'est-il pas appliqué aux fonctions de modèle?

Pendant ce temps, le prototype de operator+= Est:

template <typename CharT>
class basic_string{
    basic_string&
      operator+=(CharT _c);
};

Vous voyez, aucun modèle ici (c'est une fonction de membre de classe), donc le compilateur en déduit que le type CharT est char de l'implémentation de classe, et int(2) est automatiquement converti en char(2).


Remarque: Le code non nécessaire est supprimé lors de la copie à partir de la source d'inclusion standard C++. Cela inclut les types de noms 2 et 3 (Traits and Allocator) pour la classe de modèle "basic_string", ainsi que les caractères de soulignement superflus inutiles, afin d'améliorer la lisibilité.

47
iBug

s += 2; Ne fait pas ce que vous pensez faire. Il appelle l'opérateur surchargé += Vers un char. Cela fait pas ajouter le caractère '2', Mais plutôt le caractère avec value 2, et le résultat dépendra de l'encodage utilisé sur votre plate-forme.

Aucune surcharge de l'opérateur n'est définie pour permettre à s + 2 De se compiler.1. D'où l'erreur.

La solution dans les deux cas consiste à utiliser std::to_string(2) plutôt que le int littéral 2.


1 La raison en est essentiellement que operator+= N'est pas une fonction de modèle, mais que std::operator+ L'est, et que la résolution de surcharge favorise une fonction autre que de modèle par rapport à une autre.

43
Bathsheba

La bonne façon d’ajouter à votre string serait:

std::string s;
s += std::to_string(2);
s = s + std::to_string(2);
12
CoryKramer

Alors que @CoryKramer answer vous indique comment ajouter un entier à une chaîne, cela n'explique pas pourquoi l'instruction s = s + 2 ne compile pas.

La différence entre les deux instructions est que dans la première vous utilisez le std::string 's + = operator alors que, dans la deuxième instruction, le compilateur tente de convertir 2 à une chaîne.

Il n'y a pas de conversion implicite entre int et std::string. Cependant, vous pouvez convertir un int en char, c'est pourquoi s += 2travaux.

2
Xatyrian