如何将std :: string_view转换为const char*?

Jus*_*ond 22 c++ string string-view c++17

使用带有标志的gcc-7.1进行编译时-std=c++17,以下程序会引发错误:

#include <string_view>
void foo(const char* cstr) {}
void bar(std::string_view str){
    foo(str);
}
Run Code Online (Sandbox Code Playgroud)

错误消息是

In function 'void bar(std::string_view)':
error: cannot convert 'std::string_view {aka std::basic_string_view<char>}' to 'const char*' for argument '1' to 'void foo(const char*)'
 foo(str);
Run Code Online (Sandbox Code Playgroud)

我很惊讶没有转换,const char*因为其他库(abseil,bde)提供了string_view隐式转换为的类似类const char*.

Rak*_*111 31

A std::string_view不提供到a的转换,const char*因为它不存储以null结尾的字符串.它基本上存储了指向第一个元素的指针和字符串的长度.这意味着你不能将它传递给一个期望以空字符结尾的字符串的函数,比如foo(你还有什么方法可以获得大小?),这个字符串需要a const char*,因此决定它不值得.

如果您确定在视图中有一个以空值终止的字符串,则可以使用std::string_view::data.

如果你不是,你应该重新考虑是否首先使用a std::string_view是个好主意,因为如果你想要一个保证以空值终止的字符串std::string就是你想要的.对于单线,您可以使用std::string(object).data().

  • @rems4e 当我看到建议使用“std::string(object).data()”时,我也发出了警报,但没有重要的警告,即返回的指针指向临时 std::string 对象内的数据,该对象仅持续存在直到最大封闭表达式的末尾。 (6认同)
  • 您关于“std::string(object).data()”的建议是一个糟糕的建议,因为在大多数情况下数据将指向未分配的存储。 (2认同)
  • 请从答案中删除“std::string(object).data()”或提供明显可见的警告。这里的“std::string(object)”被释放,因此生成的 C 字符串是未定义的。我已经看到这个片段被粘贴到整个互联网和各种代码库中。这个答案造成了巨大的伤害。 (2认同)

Yak*_*ont 26

只需执行一个std::string(string_view_object).c_str()以获得有保证的以空值终止的临时副本(并在该行的末尾清除它).

这是必需的,因为字符串视图不保证空终止.例如,您可以查看较长缓冲区的中间位置.

如果这个用例很昂贵并且你已经证明它是一个瓶颈,那么你可以写一个增强的string_view跟踪它是否为空终止(基本上,如果它是从原始构造char const*).

然后你可以编写一个辅助类型,它接受这个扩充string_view并将其复制到std::stringstring_view直接存储扩充,并有一个隐式的转换char const*,返回正确的以null结尾的缓冲区.

然后在代码库中的任何地方使用该扩充的帮助器类型,而不是string_view可能增加与std字符串的字符串视图交互,以捕获具有到std字符串缓冲区末尾的视图的情况.

但实际上,这可能是矫枉过正的.

更好的方法可能是重写需要const char*采取的API string_view.

  • @sandthorn 不,直到完整表达式结束,而不是范围。 (3认同)
  • 通过“(并在行尾清理它)。”,我可以继续使用该右值的成员,直到`std::string(string_view_object).c_str()`坐的范围结束,对吗? (2认同)
  • @sandthorn如果你希望字符串保留下来,你可能更喜欢`std::string TempVar(string_view_object);`,然后在范围内需要它的地方,`TempVar.c_str()`。 (2认同)

小智 6

您可以致电foo(std::string(str).c_str())