Y a-t-il des pièges remplaçant le const const char [] par constexpr string_view?


17

Notre équipe travaille avec une base de code C ++ de 10 ans et plus et est récemment passée à un compilateur C ++ 17. Nous recherchons donc des moyens de moderniser notre code. Lors d'une conférence sur YouTube, j'ai entendu la suggestion de remplacer const char*les chaînes mondiales par constexpr string_view.

Étant donné que nous avons un certain nombre de ces const char*constantes de chaîne globales dans notre code, je veux demander s'il y a des problèmes ou des problèmes potentiels dont nous devons être conscients?

Réponses:


15

Ces problèmes méritent d'être pris en compte:

  1. std::string_viewn'a pas besoin d'être nullterminé. Donc, si vous en remplacez certains const char*par string_viewet remplacez la construction d'une sous-chaîne déjà nullterminée char*par un string_viewvia std::string_view::substr, vous ne pouvez pas passer le pointeur sous-jacent à une API qui attend une nullchaîne terminée. Exemple (sans UB, mais qui est également facilement constructible):

    void legacy(const char *str) {
       std::printf("%s\n", str);
    }
    
    constexpr std::string_view sv1 = "abcde";
    constexpr std::string_view sv2 = sv1.substr(0, 2); // view on "ab"
    
    legacy(sv2.data()); // Not intended: prints "abcde" 
  2. Bien que vous puissiez implicitement construire un à std::stringpartir d'un const char*, vous ne pouvez pas le faire avec un std::string_view. L'idée est qu'une copie complète ne devrait pas se produire sous la couverture, mais uniquement lorsqu'elle est explicitement demandée. Exemple:

    std::map<std::string, int> m;
    constexpr std::string_view sv = "somekey";
    constexpr const char *old = "somekey";
    
    m[old] = 42; // works as expected
    m[sv] = 42; // fails to compile
    m[std::string(sv)] = 42; // be explicit, this is ok

    Selon l'utilisation existante des const char*instances globales dans votre projet, ce comportement peut nécessiter une intervention manuelle à différents endroits.


que la terminaison non nulle est définitivement un piège. Maintenant, je dois passer par nos SV. Je suppose que vous feriez std::string(sv).c_str()plutôt pour passer à l'API?
darune

@darune C'est une option, mais alors les hypothèses de durée de vie de l'API devraient être vérifiées, non?! Si vous y allez someLegacyFct(std::string(sv).c_str())et que ce backend stocke en quelque sorte le pointeur ...
lubgr

c'est exact - seulement avec cette hypothèse de vie
darune

Le deuxième problème est «heureusement» ne va pas être un gros problème pour nous. Notre framework d'entreprise a sa propre classe de chaîne (je sais ...), avec un const char*constructeur explicite . Donc, la construction explicite de std::stringfrom string_viewserait juste cohérente dans notre cas.
PixelSupreme
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.