44

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

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

错误信息是

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);

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

4

3 回答 3

64

Astd::string_view不提供到 a 的转换,const char*因为它不存储以 null 结尾的 string。它基本上存储了指向第一个元素的指针和字符串的长度。这意味着您不能将它传递给期望以 null 结尾的字符串的函数,例如foo(您将如何获得大小?)期望 a const char*,因此决定它不值得。

如果您确定您的视图中有一个以 null 结尾的字符串,则可以使用std::string_view::data.

如果你不是,你应该重新考虑是否std::string_view首先使用 a 是一个好主意,因为如果你想要一个有保证的以 null 结尾的字符串std::string就是你想要的。对于单行,您可以使用std::string(object).data()注意:返回值指向一个临时 std::string实例,该实例将在表达式结束后被销毁!)。

于 2018-01-03T16:38:37.760 回答
43

只需执行 astd::string(string_view_object).c_str()即可获得有保证的空终止临时副本(并在行尾清理它)。

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

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

然后,您可以编写一个辅助类型,该类型采用此扩充string_view并将其复制到 astd::stringstring_view直接存储扩充,并具有隐式转换为 -char const*以返回正确的以空值结尾的缓冲区。

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

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

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

于 2018-01-03T17:10:47.777 回答
7

你可以打电话foo(std::string(str).c_str())

于 2018-01-03T16:49:43.907 回答