目前,我从std::vector<char>
设置了std::ostringstream
的值,如下所示:
void
foo(std::vector<char> &data, std::stringstream &stream) {
data = std::vector<char>(stream.str().begin(), stream.str().end());
}
我想知道是否有更有效的方法在C ++中使用STL或者我在这里给出的方法是否合适?我会更好地使用std::stringstream
吗?
答案 0 :(得分:10)
正如评论中所指出的,由于对str()
的两次调用,您的代码不正确。为了提高效率,您可以避免创建临时vector
,如下所示:
void foo(std::vector<char> &data, std::stringstream &stream) {
const std::string& str = stream.str();
data.assign( str.begin(), str.end() );
}
您还可以使用std::string
s:
std::istreambuf_iterator
void foo(std::vector<char> &data, std::stringstream &stream) {
data.assign(
std::istreambuf_iterator<char>( stream ), std::istreambuf_iterator<char>()
);
}
但鉴于那些是输入迭代器,vector
没有机会知道将分配多少数据并且可能执行得更糟,因为它不能reserve
足够的空间以避免重新分配。
答案 1 :(得分:9)
您的方法调用未定义的行为。 stream.str()
返回字符串 by-value ,也就是临时字符串。你获取一个临时的begin
迭代器和另一个的end
迭代器,创建一个无效的范围。
将流转换为容器的一种方法是使用公共迭代器接口:
#include <iostream>
#include <sstream>
#include <vector>
#include <algorithm>
#include <iterator>
int main(){
std::stringstream src("....");
std::vector<char> dest;
// for a bit of efficiency
std::streampos beg = src.tellg();
src.seekg(0, std::ios_base::end);
std::streampos end = src.tellg();
src.seekg(0, std::ios_base::beg);
dest.reserve(end - beg);
dest.assign(std::istreambuf_iterator<char>(src), std::istreambuf_iterator<char>());
std::copy(dest.begin(), dest.end(), std::ostream_iterator<char>(std::cout));
}
另一种方法是缓存返回的std::string
对象:
std::string const& s = stream.str();
data.reserve(s.size());
data.assign(s.begin(), s.end());
答案 2 :(得分:0)
如果有更有效的方法
您可能需要在reserve
上致电data
并直接在insert
使用范围data
成员,而不是使用副本分配。你需要记住的关于vector
的事情是每个节点都可能增加大小(并重新定位所有元素)。所以,你最好一次性分配内存(如果你知道你将存储多少个对象 - 你在这里知道)并利用这个事实。
答案 3 :(得分:0)
从流迭代器复制到后插入迭代器:
std::istream src;
std::vector<char> dst;
std::copy(std::istream_iterator<char>(src), std::istream_iterator<char>(), std::back_inserter(dst));
istream_iterator使用格式化转换(即跳过空格),因此这可能不是您想要的。我不确定你的目标是什么。