Initialise std :: string à partir d'un pointeur de caractère éventuellement NULL
Initialisation std::string
à partir d'un NULL
char pointeur est un comportement indéterminé, je crois. Donc, ici, sont des versions alternatives d'un constructeur, d'où mStdString
est une variable membre de type std::string
:
void MyClass::MyClass(const char *cstr) :
mStdString( cstr ? cstr : "")
{}
void MyClass::MyClass(const char *cstr) :
mStdString(cstr ? std::string(cstr) : std::string())
{}
void MyClass::MyClass(const char *cstr)
{
if (cstr) mStdString = cstr;
//else keep default-constructed mStdString
}
Modifier, constructeur de déclaration à l'intérieur de class MyClass
:
MyClass(const char *cstr = NULL);
Qui de ces, ou peut-être quelque chose d'autre, est la meilleure ou la plus appropriée de façon à initialiser std::string
à partir d'une NULL
pointeur, et pourquoi? Est-ce différent pour les différentes normes C++? Assumer la version normale construire des options d'optimisation.
Je suis à la recherche d'une réponse avec l'explication de pourquoi une bonne façon de faire, ou une réponse avec un lien de référence (ceci s'applique également si la réponse est "n'a pas d'importance"), et pas seulement l'opinion personnelle (mais si vous devez, au moins en faire juste un commentaire).
source d'informationauteur hyde | 2013-07-04
Vous devez vous connecter pour publier un commentaire.
Le dernier est idiot parce qu'il n'utilise pas l'initialisation quand il le pouvait.
Les deux premiers sont complètement identiques du point de vue sémantique (pensez à la
c_str()
fonction membre), c'est plutôt la première version car elle est la plus directe et idiomatiques, et facile à lire.(Il y serait être une différence sémantique si
std::string
avait unconstexpr
constructeur par défaut, mais il ne le fait pas. Pourtant, c'est possible questd::string()
est différente destd::string("")
mais je ne sais pas toutes les implémentations qui font cela, car il ne semble pas faire beaucoup de sens. D'autre part, populaire petite chaîne optimisations de nos jours signifie que les deux versions seront probablement pas effectuer toute allocation dynamique.)Mise à jour: @Jonathan, la chaîne de deux constructeurs ne sera probablement exécuter un code différent, et si ce qui compte pour vous (même si elle ne devrait pas), vous pourriez envisager une quatrième version:
À la fois lisible et de défaut de construction.
Deuxième mise à jour: Mais préfèrent
cstr ? cstr : ""
. Comme vous pouvez le voir ci-dessous, lorsque les deux branches d'appeler la même constructeur, ce qui peut être mis en œuvre de manière très efficace à l'aide conditionnelle se déplace et pas de branches. (De sorte que les deux versions ne sont en effet de générer un code différent, mais le premier est mieux).Pour le fou rire, j'ai couru les deux versions à travers Clang 3.3, avec
-O3
sur x86_64, pour unstruct foo;
comme la vôtre et une fonctionfoo bar(char const * p) { return p; }
:Constructeur par défaut (
std::string()
):Vide-chaîne constructeur (
""
):Dans mon cas, il semblerait même que
""
génère mieux code: les Deux versions appelstrlen
mais le vide-chaîne de version n'utilise pas de sauts, uniquement sous réserve se déplace (depuis le même constructeur est appelé avec deux arguments différents). Bien sûr, c'est complètement dénuée de sens, non transférables et non transférables d'observation, mais il va juste pour montrer que le compilateur n'a pas toujours besoin d'autant d'aide que vous pourriez le penser. Il suffit d'écrire le code qui semble la meilleure.En supposant que vous êtes heureux avec
cstr == NULL
produisant un videmStdString
je pense que le premier est probablement le meilleur.Si rien d'autre, la troisième option que vous fournissez ne fonctionne pas si
mStdString
estconst
. Le milieu avantages de l'option de "sémantique de déplacement" en vertu de C++11, mais est moins évidemment optimale ou raisonnable.Donc, mon vote va à la première option.
Première chose d'abord, vous avez raison, à partir de http://www.cplusplus.com/reference/string/string/string/:
Aussi, ça dépend de ce qu'est un pointeur NULL signifie pour vous. Je suppose que c'est la même chose qu'une chaîne vide pour vous.
Je voudrais aller avec le premier, car c'est la seule j'ai lu meilleur. Première solution et la seconde sont les mêmes. Troisième de ne pas fonctionner si votre chaîne est
const
.Bien que cela puisse ne pas être VRAIMENT une réponse (surtout que vous avez formulé la question) - mais c'est trop long pour tenir dans un commentaire et a du code qui n'est pas ork dans les commentaires. Je m'attends à obtenir downvoted et supprimer ce post, mais je me sens obligé de dire quelque chose.
POURQUOI l'initialisation
char *
être NULLE, et si oui, ne pouvait pas vous pousser à l'appelant de faire un certain sens de cette situation - telles que la transmission d'une chaîne vide, ou"unknown"
ou"(null)"
tant que de besoin.En d'autres termes, quelque chose comme ceci:
(Il y a probablement une façon intelligente de le faire dans un initialiseur de la liste, mais je ne peux pas être pris la peine de comprendre comment le faire correctement).
Pour ma part je n'est pas vif sur NULL comme entrée d'une chaîne de caractère en paramètre d'une autre façon que "Ce n'est pas vraiment exister" - et si c'est ce que vous êtes en fait en essayant de reproduire, alors vous devriez avoir un
boolean
- à-dire "n'existe pas", ou un pointeur vers unstd::string
qui peut être NULL si aucune chaîne n'est présent.