web-dev-qa-db-fra.com

La conversion de std :: string_view en std :: string est implicite. Qu'est-ce que l'enfer a pensé?

Sérieusement, quoi de neuf. Il y a une conversion implicite de std::string à std::string_view et ce n'est pas considéré comme dangereux. Même si cela peut sûrement causer beaucoup de références pendantes si le programmeur ne fait pas attention.

En revanche, ils ont rejeté une conversion implicite de std::string_view à std::string utilisant le même argument mais de façon complètement opposée: car le programmeur peut ne pas faire attention .

C'est très agréable qu'ils aient créé un remplacement pour un _ const char* pointeur tout en le rendant super déroutant et dénudé jusqu'à l'os:

  • Implicite const char* -> std::string: OK
  • Implicite std::string_view -> std::string: NON
  • Affectation std::string = const char*: OK
  • Affectation std::string = std::string_view: OK
  • Ajout de std::string + = const char*: OK
  • Ajout de std::string + = std::string_view: OK
  • Concaténation const char* + std::string: OK
  • Concaténation std::string_view + std::string: NON
  • Concaténation std::string + const char*: OK
  • Concaténation std::string + std::string_view: NON

Suis-je en train de manquer quelque chose ou est-ce une absurdité totale?

En fin de compte, quelle est l'utilité de cette vue de chaîne sans toutes les pièces cruciales qui la rendent similaire à const char*? Quel est l'intérêt de l'intégrer dans l'écosystème de stdlib sans faire la dernière étape pour le compléter? Après tout, si nous avions juste besoin d'un objet qui représente un morceau de chaîne, nous pourrions écrire le nôtre. En fait, beaucoup de bibliothèques l'ont déjà fait, il y a des années. L'intérêt de faire quelque chose de standard est de le rendre utile pour la plus large gamme de cas d'utilisation, n'est-ce pas?

Vont-ils résoudre ce problème dans C++ 2a?

14
GreenScape

Le problème est que std::string_view -> std::string crée une copie de la mémoire sous-jacente, complète avec l'allocation de tas, tandis que l'implicite std::string -> std::string_view ne fait pas. Si vous avez pris la peine d'utiliser un std::string_view en premier lieu, vous vous souciez évidemment des copies, vous ne voulez donc pas que cela se produise implicitement.

Considérez cet exemple:

void foo1(const std::string& x)
{
    foo2(x);
}
void foo2(std::string_view x)
{
    foo3(x);
}
void foo3(const std::string& x)
{
    // Use x...
}

La fonction foo2 aurait pu utiliser un const std::string& paramètre, mais utilisé un std::string_view pour qu'il soit plus efficace si vous passez une chaîne qui n'est pas un std::string; pas de surprise là-bas. Mais c'est moins efficace que si vous veniez de lui donner un const std::string& paramètre!

  • Quand foo2 est appelé avec un std::string argument (par exemple par foo1): Quand foo2 appels foo3, il crée une copie de la chaîne. S'il avait un const std::string& argument, il aurait pu utiliser l'objet qu'il avait déjà.
  • Quand foo2 est appelé avec un const char* argument: A std::string une copie doit être faite tôt ou tard; avec un const std::string& paramètre, il est créé plus tôt, mais dans l'ensemble, il y a exactement une copie de toute façon.

Imaginez maintenant foo2 appelle plusieurs fonctions comme foo3, ou appelle foo3 en boucle; ça fait exactement la même chose std::string objet encore et encore. Vous souhaitez que le compilateur vous en informe.

5
Arthur Tacca