我正在使用一个 boost 库,它使用boost::string_view. 但是,我想std::string_view在我的代码中使用。
问:这两者之间转换的最佳方式是什么?
目前我正在使用:
void foo(std::string_view sv) {
# ...
}
void foo(boost::string_view bsv) {
foo(std::string(bsv));
}
Run Code Online (Sandbox Code Playgroud)
但这会产生不必要的字符串。
假设我有以下代码:
void some_function(std::string_view view) {
std::cout << view << '\n';
}
int main() {
some_function(std::string{"hello, world"}); // ???
}
Run Code Online (Sandbox Code Playgroud)
viewinside会some_function指的string是已被破坏的吗?我很困惑,因为考虑到这段代码:
std::string_view view(std::string{"hello, world"});
Run Code Online (Sandbox Code Playgroud)
产生警告(来自clang++):
warning: object backing the pointer will be destroyed at the end of the full-expression [-Wdangling-gsl]
Run Code Online (Sandbox Code Playgroud)
有什么不同?
(奇怪的是,使用大括号{}而不是方括号()来初始化string_view上面的内容消除了警告。我也不知道为什么会这样。)
需要明确的是,我理解上面的警告( 的string_view寿命比 长string,所以它持有一个悬空指针)。我要问的是为什么传递 astring不会some_function产生相同的警告。
我想使用 fmt 库从我的格式参数创建 string_view 。有很多关于传递编译时字符串作为格式字符串的文档,但是,我想输出编译时字符串,以便我可以在代码的其他静态部分中使用它。有没有办法做到这一点?到目前为止,我见过的所有函数都返回一个std::string; 我也尝试过format_to,但似乎对 string_view 迭代器显式禁用(我假设它无论如何都无法在编译时工作,因为它正在变异)。这可能很简单,我只是找错了地方,我不知道。
我希望能够做类似以下的事情:
consteval std::string_view example(unsigned i){
return fmt::something<std::string_view>("You sent {}"sv, i);
}
Run Code Online (Sandbox Code Playgroud)
到目前为止,这个库似乎提供了我需要的东西,但是,避免第二个依赖将是有利的。
假设我有一个函数const string&作为其输入,例如:
void foo(const string& s);
Run Code Online (Sandbox Code Playgroud)
然后我有一个内部缓冲区const char* buffer;,我知道它的大小.
我想如果我创建字符串内联,仍然会发生一个副本:
foo(string(buffer, n));
Run Code Online (Sandbox Code Playgroud)
但是没有必要复制缓冲区,因为所有东西都是常量,我只需要字符串类的功能而不是它创建的缓冲区.
我必须提到我不确定复制是否发生,但是查看字符串的构造函数,所有人都说复制会发生.我不知道编译器优化是否可以理解这种情况,我找不到确定复制是否发生的方法.
有没有办法为字符串使用外部缓冲区,或者至少是确保复制发生与否的方法.我目前正在使用std字符串和c ++ 11.
这些方法的实现对我来说似乎很简单,它们可以使用std::string并且std::string_view更易于互换.毕竟,std::string_view具有使对象处于与这些方法相同状态的构造函数.可以解决丢失的方法,如下所示:
std::string s {"abcd"};
std::string_view v {s.c_str()};
std::cout << "ctor: " << v << std::endl; // "abcd"
v = {s.c_str() + 1, 2};
std::cout << "assign: " << v << std::endl; // "bc"
v = {nullptr}; // or even v = {};
std::cout << "clear: " << v << std::endl; // ""
Run Code Online (Sandbox Code Playgroud)
那么,在标准中不包括这两种明显方法的原因是什么?
更新:你的评论中的一个普遍问题似乎是"有什么意义?",所以我会给你一些背景信息.我正在解析一个大字符串,结果是一个子串结构.结果结构是字符串视图的自然候选者,因此我不必复制所有那些甚至重叠的字符串.部分结果是映射到字符串视图,因此我可能需要在获取密钥时将它们构造为空,并在获取值时稍后填充它们.在解析时,我需要跟踪中间字符串,这涉及更新和重置它们.现在它们也可以被字符串视图替换,这就是我在那些缺少的函数上发生的事情.当然我可以继续使用字符串或用普通的旧ptr-ptr或ptr-size对替换它们,但这正是std::string_view为了什么,对吧?
标题几乎说明了一切。
void f(const char*)
Run Code Online (Sandbox Code Playgroud)
到
void f(std::string_view)
Run Code Online (Sandbox Code Playgroud)
安全吗?如果不是,有什么陷阱?
std::string_view语义规定数组不一定是空终止,这可能是内部真正的问题,f因为已经考虑到这一点(例如,如果原始指针被传递到期望在 内终止空的函数f)。
我想做的是让我的班级在构造过程中接受一个字符串。我读到这string_view是一个替代品,const string&所以很自然地我写了一个这样的构造函数。这允许我接受 c++ 和 c 字符串。
Url::Url(boost::string_view raw_url)
: url_(static_cast<std::string>(raw_url)) {
Run Code Online (Sandbox Code Playgroud)
这里可能存在的问题是,当传递右值时,存在不必要的副本而不是移动。解决方案是制作另一个需要的构造函数string&&吗?这里的最佳实践是什么?
我有一些类型的数据std::vector<uint8_t>。我想将它解释为一个字符串并对其进行一些子字符串检查。
可以通过将其转换为std::string这将导致复制数据来完成。是否有可能以某种方式将其转换为std::string_view并对其进行搜索以避免复制它。
我正在使用这样的函数来导出 xml 文件中的数据(注意:愚蠢的例子):
void write_xml_file(const std::string& path)
{
using namespace std::string_view_literals; // Use "..."sv
FileWrite f(path);
f<< "<root>\n"sv
<< "\t<nested1>\n"sv
<< "\t\t<nested2>\n"sv
<< "\t\t\t<nested3>\n"sv
<< "\t\t\t\t<nested4>\n"sv;
//...
}
Run Code Online (Sandbox Code Playgroud)
如果这些<<需要std::string_view的参数:
FileWrite& FileWrite::operator<<(const std::string_view s) const noexcept
{
fwrite(s.data(), sizeof(char), s.length(), /* FILE* */ f);
return *this;
}
Run Code Online (Sandbox Code Playgroud)
如有必要,我可以添加重载std::string, std::array, ...
现在,我真的很想像这样写上面的内容:
// Create a compile-time "\t\t\t..."sv
consteval std::string_view indent(const std::size_t n) { /* meh? */ }
void write_xml_file(const std::string& path)
{
using namespace std::string_view_literals; …Run Code Online (Sandbox Code Playgroud) std::string_view下面这段从到转换的代码怎么可能编译std::string:
struct S {
std::string str;
S(std::string_view str_view) : str{ str_view } { }
};
Run Code Online (Sandbox Code Playgroud)
但是这个不能编译?
void foo(std::string) { }
int main() {
std::string_view str_view{ "text" };
foo(str_view);
}
Run Code Online (Sandbox Code Playgroud)
第二个给出错误:cannot convert argument 1 from std::string_view to std::string和no sutiable user-defined conversion from std::string_view to std::string exists。
应该如何foo()正确打电话呢?