介绍
我正在编写一些通信应用程序。在 C++17(没有 Boost)之前,我使用std::string
和它的 const 引用作为cls1
.
从 C++17 开始,我将std::string_view
我的代码介绍为cls2
. 但是,我没有明确的政策何时应该使用std::string_view
. 我的通信应用程序从网络接收数据并将其存储到recv_buffer
. 并从recv_buffer
.
建造
如果我只关注cls1
' 的构造函数,则移动构造是有效的。但我认为参数s
来自哪里。如果它最初来自recv_buffer
,我可以std::string_view
在接收(很早)点创建。并在recv_buffer
's 生命周期内启用,std::string_view
随处使用。如果我需要存储部分recv_buffer
然后创建std::string
.
我注意到的唯一例外recv_buffer
是始终包含我的应用程序类的完整数据。在这种情况下,移动构造是有效的。
吸气剂
我认为使用返回类型 asstd::string_view
具有优势。一些成员函数例如substr()
是有效的。但到目前为止,我没有看到任何缺点。
问题
我怀疑我可能只看到std::string_view
. 在重写许多代码之前,我想知道你的想法。
PoC 代码
#include <string>
struct cls1 {
explicit cls1(std::string s):s_(std::move(s)) {}
std::string const& get() const { return s_; }
private:
std::string s_;
};
struct cls2 {
explicit cls2(std::string_view s):s_(s) {}
std::string_view get() const { return s_; }
private:
std::string s_;
};
#include <iostream>
int main() {
// If all of the receive buffer is the target
{
std::string recv_buffer = "ABC";
cls1 c1(std::move(recv_buffer)); // move construct
std::cout << c1.get().substr(1, 2) << std::endl; // create new string
}
{
std::string recv_buffer = "ABC";
cls2 c2(recv_buffer); // copy happend
std::cout << c2.get().substr(1, 2) << std::endl; // doesn't create new string
}
// If a part of the receive buffer is the target
{
std::string recv_buffer = "<<<ABC>>>";
cls1 c1(recv_buffer.substr(3, 3)); // copy happend and move construct
std::cout << c1.get().substr(1, 2) << std::endl; // create new string
}
{
std::string recv_buffer = "<<<ABC>>>";
std::string_view ref = recv_buffer;
cls2 c2(ref.substr(3, 3)); // string create from the part of buffer directly
std::cout << c2.get().substr(1, 2) << std::endl; // doesn't create new string
}
}