任何用constexpr string_view替换全局const char []的陷阱吗?


17

我们的团队正在使用具有10多年历史的C ++代码库,并且最近切换到了C ++ 17编译器。因此,我们正在寻找使代码现代化的方法。在YouTube的一次会议演讲中,我听到了用替换const char*全局字符串的建议constexpr string_view

由于我们的代码中有很多这样的const char*全局字符串常量,因此我想问一下是否需要了解一些陷阱或潜在问题?

Answers:


15

这些问题可能值得注意:

  1. std::string_view不需要null终止。因此,如果您用const char*by string_view代替并用via 代替了以前null终止的char*子字符串的构造,则无法将基础指针传递给期望以终止的字符串的API 。示例(没有UB,但也很容易构造):string_viewstd::string_view::substrnull

    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. 虽然可以std::string从a 隐式构造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*项目中全局实例的现有用法,此行为可能需要在各个位置进行手动干预。


非零终止肯定是一个陷阱。现在,我需要检查我们的SV。我想您会std::string(sv).c_str()代替传递给API吗?
darune

@darune这是一个选项,但是应该检查API的寿命假设,对吗?如果您选择使用someLegacyFct(std::string(sv).c_str())
此后端,

这是正确的-仅在使用生命周期的前提下
-darune

第二个问题是,幸运的是,这对我们来说不是什么大问题。我们公司的框架具有自己的字符串类(我知道...),带有显式const char*构造函数。所以std::stringfrom的显式构造string_view在我们的情况下将是一致的。
PixelSupreme
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.