std::stringstream
初始化构造函数接受const string&
作为参数:
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等替代方案?
发布于 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
explicit basic_stringstream( std::basic_string<CharT,Traits,Allocator>&& str,
std::ios_base::openmode mode =
std::ios_base::in | std::ios_base::out );
str
构造底层字符串设备的内容。底层basic_stringbuf
对象被构造为basic_stringbuf<Char,Traits,Allocator>(std::move(str), mode)
。而且,由于std::string
是来自string_view
的可构造的,将std::string_view
传递到std::stringstream
构造函数中将使用移动构造函数重载,这将使复制最小化。
因此,实际上不需要使用string_view
-specific构造函数。
发布于 2022-09-03 06:26:45
如何有效地(如果您愿意的话使用std::move()
)使用std::string
、std::string_view
或C-字符串在C++11或更高版本中构造一个std::string_view
快速总结
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 220
E 124。如下所示.
您可以在我的string.cpp文件中的世界回购中使用这些测试示例。
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();
样本输出:
Hello world.
Hey and how are you today?
Hey and how are you doing?
Hey and how are you doing?
参考文献
std::stringstream
构造函数:串流std::string
构造函数,以从std::string_view
:字符串 创建一个字符串std::string
构造函数,以从C-字符串(const char*
)创建一个std::string
。https://stackoverflow.com/questions/73589589
复制相似问题