首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么std::std流不能与std::string_view一起工作?

为什么std::std流不能与std::string_view一起工作?
EN

Stack Overflow用户
提问于 2022-09-03 04:19:51
回答 2查看 227关注 0票数 4

std::stringstream初始化构造函数接受const string&作为参数:

代码语言:javascript
运行
复制
explicit stringstream (const string& str,
                       ios_base::openmode which = ios_base::in | ios_base::out);

这个接口在C++98中是合理的,但是由于C++17,我们使用std::string_view作为表示字符串的类的更便宜的替代方案。std::stringstream类不修改它接受的字符串,不拥有它,它不要求它以空结尾。那么,为什么不添加另一个接受std::string_view的构造函数重载呢?是否有任何障碍使这一解决方案不可能(或不合理)屈服于诸如Boost::Iostreams等替代方案?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-09-03 04:38:00

在这一点上(即:当我们接近C++23),它只是没有太多的意义。

由于您使用的是stringstream,而不是更特定于使用的版本之一,所以有两种可能:您希望能够写入流,或者不写入。

如果不打算写入流,则不需要复制数据。所有形式的stringstream都拥有它所作用的字符,所以您应该尽量避免复制。您可以使用C++23类型的ispanstream (替代旧的strstream)。这需要一个span<const CharT>,但是string_view 也是构造者

如果您确实打算写入流,则需要将数据复制到stringstream中。但你不需要做两次拷贝。因此C++20为stringstream提供了一个来自std::string的移动构造函数。请参阅这里的构造函数#6

代码语言:javascript
运行
复制
explicit basic_stringstream( std::basic_string<CharT,Traits,Allocator>&& str,
                             std::ios_base::openmode mode = 
                             std::ios_base::in | std::ios_base::out );

  1. 移动-用str构造底层字符串设备的内容。底层basic_stringbuf对象被构造为basic_stringbuf<Char,Traits,Allocator>(std::move(str), mode)

而且,由于std::string是来自string_view的可构造的,将std::string_view传递到std::stringstream构造函数中将使用移动构造函数重载,这将使复制最小化。

因此,实际上不需要使用string_view-specific构造函数。

票数 8
EN

Stack Overflow用户

发布于 2022-09-03 06:26:45

如何有效地(如果您愿意的话使用std::move() )使用std::stringstd::string_view或C-字符串在C++11或更高版本中构造一个std::string_view

快速总结

代码语言:javascript
运行
复制
std::string str("Hello ");                            // std::string
constexpr char c_str[] = "Hey and how are you ";      // C-string
std::string_view sv(c_str);                           // std::string_view

std::stringstream ss1(str);                           // from a std::string
std::stringstream ss3(std::move(std::string(c_str))); // from a C-string
std::stringstream ss2(std::move(std::string(sv)));    // from a std::string_view

详细信息

我刚刚用@Nicol更新了被接受的答案,其中包含了来自串流的C++20移动构造函数(构造函数#6)定义和解释。但是,如果您正在使用C++11,您仍然可以通过自己调用std::move()来提高效率(据我所知)。

无论是否显式调用std::move(),下面的三种技术都可以从<代码>e 225从e 225从** std::string_view**,或从C字符串(**char <std::string_view**,>E 135数组中构造std::stringstream,因此,实际上不需要从(**char构造额外的构造函数,因为已经从E 220std::string_view**,>E 124中构造了一个E 220E 124。如下所示.

您可以在我的string.cpp文件中的世界回购中使用这些测试示例。

代码语言:javascript
运行
复制
std::string str("Hello ");                          // std::string
constexpr char c_str[] = "Hey and how are you ";    // C-string
std::string_view sv(c_str);                         // std::string_view

// 1. Construct a `std::stringstream` from a `std::string`. This is
// constructor #3 from the link below: reference page for the
// `std::stringstream` constructors:
// https://en.cppreference.com/w/cpp/io/basic_stringstream/basic_stringstream
// - Open in mode `std::ios_base::app` as well in order to **append** all new
//   writes to the end of the stream! See link above **and**:
//   https://stackoverflow.com/a/8786212/4561887
std::stringstream ss1(str, 
    std::ios_base::in | std::ios_base::out | std::ios_base::app);
ss1 << "world.\n";  // since `std::ios_base::app` was used above, this 
                    // **appends** rather than **overwrites** the data in 
                    // the stringstream.
std::cout << ss1.str() << "\n";

// 2. Construct a `std::stringstream` from a `std::string_view`. This is also
// constructor #3 from the link above (passing in a `std::string), but we must
// first construct a `std::string` from the `std::string_view`. We are using
// constructor #10 from the `std::string` constructors shown here to create a
// `std::string` from a `std::string_view`:
// https://en.cppreference.com/w/cpp/string/basic_string/basic_string
// - See also the note about the `std::ios_base::app` mode above.
std::stringstream ss2b(std::move(std::string(sv)),
    std::ios_base::in | std::ios_base::out | std::ios_base::app);
ss2b << "today?\n";
std::cout << ss2b.str() << "\n";

// 3. Construct a `std::stringstream` from a C-string. This is also
// constructor #3 from the link above (passing in a `std::string), but we must
// first construct a `std::string` from the C-string. We are using
// constructor #5 from the `std::string` constructors shown here to create a
// `std::string` from a C-string (`const char*`):
// https://en.cppreference.com/w/cpp/string/basic_string/basic_string
// - See also the note about the `std::ios_base::app` mode above. Note that the
//   C-string is used to automatically, implicitly construct a `std::string`
//   here, I believe.
//
// implicit construction of `std::string` from `c_str`
std::stringstream ss3c(std::move(c_str),
    std::ios_base::in | std::ios_base::out | std::ios_base::app);
ss3c << "doing?\n";
std::cout << ss3c.str();
// explicit construction of `std::string` from `c_str`
std::stringstream ss3d(std::move(std::string(c_str)),
    std::ios_base::in | std::ios_base::out | std::ios_base::app);
ss3d << "doing?\n";
std::cout << ss3d.str();

样本输出:

代码语言:javascript
运行
复制
Hello world.
Hey and how are you today?
Hey and how are you doing?
Hey and how are you doing?

参考文献

  1. std::stringstream构造函数:串流
  2. 构造函数#10来自此处所示的std::string构造函数,以从std::string_view字符串 创建一个字符串
    1. 和构造函数#5来自这里显示的std::string构造函数,以从C-字符串(const char*)创建一个std::string

  3. 如何将内容附加到字符串类型对象?
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73589589

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档