Gibt es Fallstricke, die das globale const char [] durch constexpr string_view ersetzen?

17

Unser Team arbeitet mit einer über 10 Jahre alten C ++ - Codebasis und hat kürzlich auf einen C ++ 17-Compiler umgestellt. Deshalb suchen wir nach Möglichkeiten, unseren Code zu modernisieren. In einem Konferenzgespräch auf YouTube hörte ich den Vorschlag, const char*globale Zeichenfolgen durch zu ersetzen constexpr string_view.

Da wir eine ganze Reihe solcher const char*globalen Zeichenfolgenkonstanten in unserem Code haben, möchte ich fragen, ob es Fallstricke oder potenzielle Probleme gibt, die wir beachten müssen.

PixelSupreme
quelle

Antworten:

15

Diese Probleme sollten beachtet werden:

  1. std::string_viewmuss nicht beendet werden null. Wenn Sie also einige const char*durch string_viewersetzen und die Konstruktion eines zuvor nullterminierten char*Teilstrings durch ein string_viewvia ersetzen std::string_view::substr, können Sie den zugrunde liegenden Zeiger nicht an eine API übergeben, die einen nullterminierten String erwartet . Beispiel (ohne UB, aber das ist auch leicht zu konstruieren):

    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. Während Sie implizit a std::stringaus a konstruieren können const char*, können Sie dies nicht mit a tun std::string_view. Die Idee ist, dass eine tiefe Kopie nicht unter dem Deckblatt erfolgen sollte, sondern nur auf ausdrückliche Anfrage. Beispiel:

    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

    Abhängig von der vorhandenen Verwendung der globalen const char*Instanzen in Ihrem Projekt erfordert dieses Verhalten möglicherweise manuelle Eingriffe an verschiedenen Stellen.

lubgr
quelle
Diese Nicht-Null-Kündigung ist definitiv ein Gotcha - auch. Jetzt muss ich unsere SVs durchgehen. Ich nehme an, Sie würden std::string(sv).c_str()stattdessen für die Übergabe an API tun ?
Darune
@darune Das ist eine Option, aber dann sollten die Lebenszeitannahmen der API überprüft werden, oder?! Wenn Sie mitgehen someLegacyFct(std::string(sv).c_str())und dieses Backend irgendwie den Zeiger speichert ...
lubgr
das ist richtig - nur mit dieser lebenslangen Annahme
darune
Das zweite Problem ist "zum Glück", dass es für uns keine große Sache sein wird. Unser Unternehmensframework verfügt über eine eigene Zeichenfolgenklasse (ich weiß ...) mit einem expliziten const char*Konstruktor. Eine explizite Konstruktion von std::stringfrom string_viewwäre also in unserem Fall nur konsistent.
PixelSupreme