Введение
Я пишу какое-то коммуникационное приложение. До C ++ 17 (без Boost) я использовал std::string
и его константную ссылку как cls1
.
Начиная с C ++ 17, я ввел std::string_view
в свой код как cls2
.
Тем не менее, у меня нет четкой политики, когда мне следует использовать std::string_view
. Мое коммуникационное приложение получает данные из сети и сохраняется в recv_buffer
. И создает некоторые классы приложений из recv_buffer
.
Строительство
Если я сфокусируюсь только на конструкторе cls1
, построение перемещения будет эффективным. Но я думаю, что, где параметр s
от. Если он изначально из recv_buffer
, я могу создать std::string_view
в точке получения (очень рано). И в течение времени жизни recv_buffer
, используйте std::string_view
везде. Если мне нужно сохранить часть recv_buffer
, создайте std::string
.
Единственное исключение, которое я заметил, - recv_buffer
всегда содержит полные данные для моего класса приложения. В этом случае эффективная конструкция перемещения.
Getter
Я думаю, что использование типа возврата как std::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
}
}
Запуск демо: https://wandbox.org/permlink/TW8w3je3q3D46cjk