任何用 constexpr string_view 替换全局 const char[] 的陷阱?
Posted
技术标签:
【中文标题】任何用 constexpr string_view 替换全局 const char[] 的陷阱?【英文标题】:Any gotchas replacing global const char[] with constexpr string_view? 【发布时间】:2019-10-08 07:31:43 【问题描述】:我们的团队正在使用具有 10 多年历史的 C++ 代码库,并且最近切换到了 C++17 编译器。所以我们正在寻找使我们的代码现代化的方法。在 YouTube 上的一次会议演讲中,我听到了建议,将 const char*
全局字符串替换为 constexpr string_view
。
由于我们的代码中有很多这样的const char*
全局字符串常量,我想问一下是否有任何我们需要注意的问题或潜在问题?
【问题讨论】:
【参考方案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"
虽然您可以从const char*
隐式构造std::string
,但您不能使用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*
实例的现有使用情况,此行为可能需要在不同位置进行人工干预。
【讨论】:
非零终止肯定是一个陷阱-auch。现在我需要检查我们的 SV。我想你会用std::string(sv).c_str()
代替传递给 API 吗?
@darune 这是一个选项,但是应该检查 API 的生命周期假设,对吧?!如果你使用someLegacyFct(std::string(sv).c_str())
并且这个后端以某种方式存储指针......
这是正确的 - 仅在生命周期假设下
第二个问题是“幸运的是”对我们来说没什么大不了的。我们公司的框架有它自己的字符串类(我知道......),带有一个显式的const char*
构造函数。因此,在我们的案例中,从 string_view
显式构造 std::string
将是一致的。以上是关于任何用 constexpr string_view 替换全局 const char[] 的陷阱?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 constexpr string_view 上使用 std::string_view::remove_prefix()