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.
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é.
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.
La bonne façon d’ajouter à votre string
serait:
std::string s;
s += std::to_string(2);
s = s + std::to_string(2);
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 += 2
travaux.