我有一个方法,它采用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
,因为我在其中传递了不同类型的字符串。
你不能通过std::string_view
改变一个字符串。因此,您无法添加终止'\0'
字符。因此,您需要将字符串复制到其他位置以添加'\0'
终结符。如果字符串足够短,可以通过将字符串放在堆栈上来避免堆分配。如果你知道,std::string_view
是一个以null结尾的字符串的一部分,那么你可以检查一下,如果结尾的字符是'\0'
字符并且在那种情况下避免复制。除此之外,我没有看到更多的优化空间。
我通过创建一个名为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
s应该是NUL终止的。像std::string
一样,NUL字符不是字符串大小的一部分,但它就在那里。
我发现它对于处理C接口非常有用。
你当然不应该在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());
}