例如,如果我使用这样的代码,该缓冲区内的内存工作是否会出现问题?我可以使用输入流并使用具有相同streambuf的sv(string_view)吗?
boost::asio::streambuf buf_;
std::ostream out(&buf_);
int a = 1488;
out << a;
out << 33;
out << 100005l;
std::basic_string_view<uint8_t> arr_ {boost::asio::buffer_cast<const uint8_t *>(buf_.data()), buf_.size()};
std::istream in(&buf_);
int g;
in >> g;
int d = ArrayToValue<int>(&arr_[0]);
既然我希望答案是肯定的,是否会出现问题,如果是这样,在缓冲区已满之前不会使用 string_view 吗?也就是说,在填充并从该缓冲区读取之后,将其与输入流一起使用!
最佳答案
streambuf::data()
返回一个缓冲区序列。所以不能保证你有string_view
一般来说,绘制其全部容量。
The
basic_streambuf
class is derived fromstd::streambuf
to associate the streambuf's input and output sequences with one or more character arrays.
但是,文档继续提到
The
basic_streambuf
class's public interface is intended to permit the following implementation strategies:
- A single contiguous character array, which is reallocated as necessary to accommodate changes in the size of the character sequence. This is the implementation approach currently used in Asio.
- A sequence of one or more character arrays, where each array is of the same size. Additional character array objects are appended to the sequence to accommodate changes in the size of the character sequence.
- A sequence of one or more character arrays of varying sizes. Additional character array objects are appended to the sequence to accommodate changes in the size of the character sequence.
(已添加突出显示)
所以,如果你断言了你的假设,那么你现在可能会逃脱惩罚:
assert(buf_.data().begin() + 1 == buf_.data().end());
auto first = *buf_.data().begin();
std::basic_string_view<uint8_t> arr_( //
buffer_cast<const uint8_t*>(first), //
first.size());
但是,一旦您使用std::istream
在streambuf对象上,它将执行
调用basic_stream_buf::consume()
,它没有明确记录这一点
它不会重新分配。
但是,此模型的 DynamicBuffer_v1 概念 documents :
则删除整个输入序列。之前使用data() 或prepare() 获得的所有常量或可变缓冲区
序列均无效。
因此,为了遵循库模式,似乎最好不要依赖于
string_view
阅读 istream
后保持有效.
另请注意,最好限制 istream
的范围/ostream
对象:
boost::asio::streambuf buf_;
{
std::ostream out(&buf_);
int a = 1488;
out << a;
out << 33;
out << 100005l;
}
assert(buf_.data().begin() + 1 == buf_.data().end());
auto first = *buf_.data().begin();
std::basic_string_view<uint8_t> arr_( //
buffer_cast<const uint8_t*>(first), //
first.size());
{
std::istream in(&buf_);
int g;
in >> g;
}
或者甚至:
int const a = 1488;
boost::asio::streambuf buf_;
std::ostream(&buf_) << a << 33 << 100005l;
assert(buf_.data().begin() + 1 == buf_.data().end());
auto first = *buf_.data().begin();
std::basic_string_view<uint8_t> arr_( //
buffer_cast<const uint8_t*>(first), //
first.size());
int g;
std::istream(&buf_) >> g;
更新
根据以下发现,有一种比上述所有策略更快的策略
评论:const_buffers_1
奇怪的是,里氏可替代单个
缓冲。您可以让编译器检查这一点:
asio::const_buffer const& first = buf_.data();
如果 Asio 的 future 版本更改了实现,则无法编译
战略。请注意,最近您应该更喜欢拼写缓冲区类型
BOOST_ASIO_CONST_BUFFER
或BOOST_ASIO_MUTABLE_BUFFER
相反,所以你的代码
不依赖于 BOOST_ASIO_NO_DEPRECATED
的配置.
<强> Live On Coliru
#include <boost/asio.hpp>
namespace asio = boost::asio;
int main() {
asio::streambuf sb;
sb.commit(asio::buffer_copy(sb.prepare(32), asio::buffer("Hello World!", 12)));
asio::BOOST_ASIO_CONST_BUFFER const& first = sb.data(); // proves single buffer assumption
assert(first.size() == 12);
}
关于c++ - 使用 boost::asio::streambuf 作为 istream 和数组作为 string_view 是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72236319/