我有一个方法,它接受std::string_view
并使用函数,它以null终止字符串作为参数。例如:
void stringFunc(std::experimental::string_view str) {
some_c_library_func(/* Expects null terminated string */);
}
问题是,处理这种情况的正确方法是什么? str.to_string().c_str()
是唯一的选择吗?我真的想在这个方法中使用std::string_view
,因为我在其中传递了不同类型的字符串。
答案 0 :(得分:13)
我通过创建名为string_view
的备用zstring_view
类来解决此问题。它是私有地继承自string_view
并包含其大部分接口。
主要区别在于无法从zstring_view
创建string_view
。此外,任何从末尾删除元素的string_view
API都不是界面的一部分,或者它们返回string_view
而不是zstring_view
。
可以从任何以NUL结尾的字符串源创建它们:std::string
,依此类推。我甚至为它们创建了特殊的用户定义的文字后缀:_zsv
。
这个想法是,只要你不手动将非NUL终止的字符串放入zstring_view
,所有zstring_view
都应该以NUL终止。与std::string
类似,NUL字符不是字符串大小的一部分,但它是那里。
我发现它对于处理C接口非常有用。
答案 1 :(得分:6)
您无法通过std::string_view
更改字符串。因此,您无法添加终止'\0'
字符。因此,您需要将字符串复制到其他位置以添加'\0'
- 终止符。如果字符串足够短,可以通过将字符串放在堆栈上来避免堆分配。如果您知道,std::string_view
是以空字符结尾的字符串的一部分,那么您可以检查,如果结尾的字符是'\0'
字符,并在这种情况下避免复制。除此之外,我没有看到更多的优化空间。
答案 2 :(得分:5)
您当然不应在data
上致电std::experimental::string_view
:
与basic_string :: data()和字符串文字不同,data()可能返回一个 指向非空终止缓冲区的指针。
请致电to_string
和c_str
:
void stringFunc(std::experimental::string_view str) {
some_c_library_func(str.to_string().c_str());
}
或:
void stringFunc(std::experimental::string_view str) {
std::string real_str(str);
some_c_library_func(real_str.c_str());
}
答案 3 :(得分:0)
在某些情况下,C-stype 函数有重载,它接受字符串的长度作为单独的参数。
例如而不是使用 strcasesmp()
值得切换到 strncasecmp()
。
当然,在这种特殊情况下,如果字符串不相等,但前 n 个字符相等,则需要实现额外的逻辑。
但它可能是为字符串视图编写自定义类的不错选择。