7

現在、次のようstd::vector<char>に an から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

コメントで指摘されているように、への2つの呼び出しが原因で、コードが正しくありませんstr()。効率を向上させるために、次vectorのような一時的な作成を回避できます。

void foo(std::vector<char> &data, std::stringstream &stream) {
    const std::string& str = stream.str();
    data.assign( str.begin(), str.end() );
}

sstd::stringを使用してを回避することもできます。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

于 2012-05-30T19:55:49.923 に答える
10

あなたのメソッドは未定義の動作を呼び出します。文字列by-value、別名一時文字列をstream.str()返します。1 つのテンポラリのイテレータともう 1 つのイテレータを使用して、無効な範囲を作成します。beginend

ストリームをコンテナーに変換する 1 つの方法は、共通の反復子インターフェイスを使用することです。

#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 での実例。

もう 1 つの方法は、返された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をお勧めします。覚えておく必要があるのは、すべてのノードがサイズを大きくする可能性がある(そしてすべての要素を再配置する)可能性があるということです。したがって、一度にメモリを割り当てて(格納するオブジェクトの数がわかっている場合は、ここで知っている)、この事実を活用することをお勧めします。datainsertdatavector

于 2012-05-30T19:55:44.863 に答える