Introduction
I'm writing some communication application. Before C++17 (without Boost), I use std::string and its const reference as cls1.
Since C++17, I introduced std::string_view to my code as cls2.
However, I don't have clear policy when should I use std::string_view. My communication application receives data from the network and it is stored to recv_buffer. And creates some application classes from recv_buffer.
Construction
If I focus only cls1's constructor, move construction is efficient. But I think that where the parameter s from. If it is originally from the recv_buffer, I can create std::string_view at the receiving (very early) point. And during recv_buffer's lifetime is enabled, use std::string_view everywhere. If I need to store the part of recv_buffer then create std::string.
An only exception I noticed is the recv_buffer is always contained complete data for my application class. In this case, move construction is efficient.
Getter
I think using the return type as std::string_view has advantage. Some member function such as substr() is efficient. But I don't see any disadvantage, so far.
Question
I suspect that I might see only pros of std::string_view. Before re-writing many codes, I would like to know your ideas.
PoC code
#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
}
}
Running Demo: https://wandbox.org/permlink/TW8w3je3q3D46cjk