7

std::vector<char>目前,我将 a的值设置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吗?

4

4 回答 4

12

正如评论中指出的那样,由于两次调用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通过使用std::istreambuf_iterators 来避免:

void foo(std::vector<char> &data, std::stringstream &stream) {
    data.assign(
        std::istreambuf_iterator<char>( stream ), std::istreambuf_iterator<char>()
    );
}

但鉴于这些是输入迭代器vector因此没有机会知道将分配多少数据并且可能执行得更差,因为它没有reserve足够的空间来避免重新分配。

于 2012-05-30T19:55:49.923 回答
10

您的方法调用未定义的行为按值stream.str()返回一个字符串,也就是一个临时字符串。您使用一个临时的迭代器和另一个的迭代器,创建一个无效的范围。beginend

将流转换为容器的一种方法是使用通用迭代器接口:

#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));
}

Ideone 上的实时示例。

另一种方法是缓存返回的std::string对象:

std::string const& s = stream.str();
data.reserve(s.size());
data.assign(s.begin(), s.end());
于 2012-05-30T19:58:12.837 回答
3

从流迭代器复制到后插入迭代器:

std::istream src;
std::vector<char> dst;

std::copy(std::istream_iterator<char>(src), std::istream_iterator<char>(), std::back_inserter(dst));

istream_iterator 使用格式化转换(即跳过空格),因此这可能不是您想要的。我不确定你的目标是什么。

于 2012-05-30T20:47:33.547 回答
0

如果有更有效的方法

reserve您可能希望直接调用data并使用范围insert成员,data而不是使用复制分配。vector您需要记住的关于 s 的事情是每个节点都可能会增加大小(并重新定位所有元素)。所以,你最好一次性分配内存(如果你知道你将存储多少个对象——你在这里知道)并利用这个事实。

于 2012-05-30T19:55:44.863 回答