Любые ошибки заменить глобальный const char [] на constexpr string_view?

17

Наша команда работает с базой кода C ++ более 10 лет и недавно перешла на компилятор C ++ 17. Поэтому мы ищем способы модернизировать наш код. В ходе конференции на YouTube я услышал предложение заменить const char*глобальные строки на constexpr string_view.

Поскольку const char*в нашем коде есть довольно много таких глобальных строковых констант, я хочу спросить, есть ли какие-то ошибки или потенциальные проблемы, о которых нам нужно знать?

PixelSupreme
источник

Ответы:

15

Эти вопросы, возможно, стоит знать:

  1. std::string_viewне должен быть определен null. Так что, если заменить некоторые const char*на string_viewи заменить конструкцию ранее null-завершённых char*подстрок по с string_viewпомощью std::string_view::substr, вы не можете передать указатель , лежащий на API, ожидающий null-завершённую строку. Пример (без UB, но это тоже легко построить):

    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. Хотя вы можете неявно создать a std::stringиз a const char*, вы не можете сделать это с помощью a std::string_view. Идея заключается в том, что глубокая копия не должна происходить под прикрытием, а только при явном запросе. Пример:

    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
    

    В зависимости от существующего использования глобальных const char*экземпляров в вашем проекте, такое поведение может потребовать ручного вмешательства в различных местах.

lubgr
источник
что ненулевое завершение определенно является ошибкой Теперь мне нужно пройти через наши SV. Я полагаю, вы бы std::string(sv).c_str()вместо этого перейти на API?
Даруна
@darune Это вариант, но тогда нужно проверить предположения API на весь срок службы, верно ?! Если вы идете с someLegacyFct(std::string(sv).c_str())и этот бэкэнд каким-то образом хранит указатель ...
lubgr
это правильно - только с этим предположением жизни
darune
Вторая проблема, к счастью, не будет для нас большой. Фреймворк нашей компании имеет собственный строковый класс (я знаю ...) с явным const char*конструктором. Так что явная конструкция std::stringfrom string_viewбудет просто последовательной в нашем случае.
PixelSupreme