将原始字节数组读入到std::string中

6

我一直在思考以下问题:假设我有一个C风格的函数,它可以将原始数据读入缓冲区。

int recv_n(int handle, void* buf, size_t len);

我能直接将数据读入std:stringstringstream中,而不需要分配任何临时缓冲区吗?例如:

std::string s(100, '\0');
recv_n(handle, s.data(), 100);

我猜这个解决方案的结果未定义,因为据我所知,string::c_strstring::data可能会返回临时位置,而不一定返回指向对象用于存储数据的实际内存位置的指针。

有什么想法吗?

2个回答

12

为什么不使用vector<char>而使用string?这样你可以做到:

vector<char> v(100, '\0');
recv_n(handle, &v[0], 100);

在我看来,这个更符合惯用语,特别是因为你不把它当做字符串使用(你说它是原始数据)。


C++11:recv_n(handle, v.data(), 100); - Chinasaur
@Chinasaur:我认为需要进行强制类型转换,因为有 const - Mooing Duck
令人困惑的是,vector::data() 不是 const 的,但 string::data() 是。 - Chinasaur

11

是的,在C++11之后可以实现。

但是你不能使用 s.data(),因为它返回一个 char const*

尝试:

std::string s(100, '\0');
recv_n(handle, &s[0], 100);

根据情况,我可能会选择std::vector<char>来处理原始数据(不过这完全取决于您的应用程序中对数据的使用方式)。


我认为这可能行不通,因为s[0]s.data()[0]相同,可能指向临时位置。 - FireAphis
2
@FireAphis:不是的,s[0]和s.data()[0]不同。区别在于,如果字符串使用写时复制实现,它必须确保在返回引用之前该字符串是唯一的。这就是为什么s[0]返回对char的引用而不是对const char的引用。data()返回const char*的原因是字符串数据可能与多个字符串实例共享。因此,当您执行&s[0]时,您可以确保拥有指向连续未共享字符串的指针。 - Martin York
我认为这也不是一种安全的方法,主要是因为我相信 std::string 并没有保证存储是连续的 - 当然对于这样一个小块,它可能是连续的,但是没有保证(除非这是 C++x0),@chrisaycock 的方法更安全。 - Nim
@Nim:您说得对。我不相信C++03标准保证了这一点。但我相信C++0x确实有(因为他们想能够将可变字符串传递给C接口函数),并且作为分析的一部分,他们查看了当前的实现,并发现STL的当前所有实现都使用连续的空间来存储&s[0]。 - Martin York
在C++11中确实有保证。在C++03中没有保证,但是使用其他方式实现字符串是不切实际的,所以是的,每个人都让它连续了。 - Mooing Duck

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接