Si vous faites partie du groupe "Presque Toujours Auto", alors l'UDL est très importante. Elle vous permet de faire ceci :
auto str = "Foo"s;
Et ainsi, str
sera un véritable std::string
, et non un const char*
. Cela vous permet donc de décider quand faire quoi.
C'est également important pour la déduction du type de retour automatique :
[]() {return "Foo"s;}
Ou toute forme de déduction de type, en réalité :
template
void foo(T &&t) {...}
foo("Foo"s);
Le seul avantage que je vois à utiliser [...] au lieu de [...] est qu'avec le premier cas, le compilateur peut effectuer une élision de copie (je pense), ce qui serait plus rapide que l'appel au constructeur dans le second cas.
L'élision de copie n'est pas plus rapide que l'appel au constructeur. De toute façon, vous appelez un des constructeurs de l'objet. La question est lequel :
std::string str = "foo";
Cela provoquera un appel au constructeur de std::string
qui prend un const char*
. Mais puisque std::string
doit copier la chaîne dans son propre espace de stockage, elle doit obtenir la longueur de la chaîne pour le faire. Et puisqu'elle ne connaît pas la longueur, ce constructeur doit utiliser strlen
pour l'obtenir (techniquement, char_traits::length
, mais ce n'est probablement pas beaucoup plus rapide).
En revanche :
std::string str = "foo"s;
Cela utilisera le modèle UDL qui a ce prototype :
string operator "" s(const char* str, size_t len);
Voyez-vous, le compilateur connaît la longueur d'une chaîne littérale. Ainsi, le code UDL reçoit un pointeur vers la chaîne et une taille. Et donc, il peut appeler le constructeur de std::string
qui prend un const char*
et un size_t
. Ainsi, il n'est pas nécessaire de calculer la longueur de la chaîne.
Le conseil en question n'est pas que vous convertissiez chaque utilisation d'une littérale en la version s
. Si vous êtes bien avec les limitations d'un tableau de char
s, utilisez-le. Le conseil est que, si vous allez stocker cette littérale dans un std::string
, il est préférable de le faire pendant qu'il est encore une littérale et non un const char*
nébuleux.
3 votes
Errr... Est-ce que la déduction de type
auto
compte ? Le conseil presque toujoursauto
suscite en effet quelque controverse.1 votes
Beaucoup de choses en C++ sont liées à la sémantique. L'idéal est de décrire aussi précisément que possible ce que vous voulez faire, et de laisser le compilateur gérer tout le reste. Cependant, ne pas en faire trop pour laisser le compilateur avoir de la marge de manœuvre (et optimiser).
3 votes
Considérez le cas où vous passez une chaîne littérale en tant que paramètre avec un type qui est constructible à partir de
std::string
, mais pas à partir d'une chaîne C.0 votes
@NickyC Non ça ne l'est pas :)
0 votes
@chris N'y avez pas pensé, merci
1 votes
Pour c++17 dans certains cas
string_view
peut être préférable pour stocker littéraux, car il ne 'touche pas au tas'.0 votes
@PaulRooney Bon point :)
2 votes
@PaulRooney,
string_view
est extrêmement utile, mais gardez à l'esprit que la plupart des implémentations destd::string
non plus pour les chaînes courtes.