4 文字のみをコピーしています (システムのポインター幅によって異なります)。これにより、null 以外で終了する 4 文字以上の文字数が残り、atoi への入力でランナウェイ文字列が発生します。
sizeof(str.c_str()) //i.e. sizeof(char*) = 4 (32 bit systems)
する必要があります
str.length() + 1
または、文字は nullterminate されません
STL のみ:
make_testdata()
: ずっと下を見る
ストリームを使用しないのはなぜですか...?
#include <sstream>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <string>
#include <vector>
int main()
{
std::vector<int> data = make_testdata();
std::ostringstream oss;
std::copy(data.begin(), data.end(), std::ostream_iterator<int>(oss, "\t"));
std::stringstream iss(oss.str());
std::vector<int> clone;
std::copy(std::istream_iterator<int>(iss), std::istream_iterator<int>(),
std::back_inserter(clone));
//verify that clone now contains the original random data:
//bool ok = std::equal(data.begin(), data.end(), clone.begin());
return 0;
}
単純な C では、atoi/itoa といくつかの微調整を使用して、はるかに高速に実行できますが、速度が必要な場合は、バイナリ転送を使用する必要があると思います (優れたライブラリについては、 Boost Spirit Karmaとprotobufを参照してください)。
カルマ/気のブースト:
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/karma.hpp>
namespace qi=::boost::spirit::qi;
namespace karma=::boost::spirit::karma;
static const char delimiter = '\0';
int main()
{
std::vector<int> data = make_testdata();
std::string astext;
// astext.reserve(3 * sizeof(data[0]) * data.size()); // heuristic pre-alloc
std::back_insert_iterator<std::string> out(astext);
{
using namespace karma;
generate(out, delimit(delimiter) [ *int_ ], data);
// generate_delimited(out, *int_, delimiter, data); // equivalent
// generate(out, int_ % delimiter, data); // somehow much slower!
}
std::string::const_iterator begin(astext.begin()), end(astext.end());
std::vector<int> clone;
qi::parse(begin, end, qi::int_ % delimiter, clone);
//verify that clone now contains the original random data:
//bool ok = std::equal(data.begin(), data.end(), clone.begin());
return 0;
}
代わりに、アーキテクチャに依存しないバイナリ シリアライゼーションを行いたい場合は、この小さな適応を使用して、物事を無数倍高速化します (以下のベンチマークを参照してください... )。
karma::generate(out, *karma::big_dword, data);
// ...
qi::parse(begin, end, *qi::big_dword, clone);
シリアライゼーションのブースト
バイナリ モードでブースト シリアライゼーションを使用すると、最高のパフォーマンスが得られます。
#include <sstream>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/vector.hpp>
int main()
{
std::vector<int> data = make_testdata();
std::stringstream ss;
{
boost::archive::binary_oarchive oa(ss);
oa << data;
}
std::vector<int> clone;
{
boost::archive::binary_iarchive ia(ss);
ia >> clone;
}
//verify that clone now contains the original random data:
//bool ok = std::equal(data.begin(), data.end(), clone.begin());
return 0;
}
テストデータ
(上記全バージョン共通)
#include <boost/random.hpp>
// generates a deterministic pseudo-random vector of 32Mio ints
std::vector<int> make_testdata()
{
std::vector<int> testdata;
testdata.resize(2 << 24);
std::generate(testdata.begin(), testdata.end(), boost::mt19937(0));
return testdata;
}
ベンチマーク
私はそれをベンチマークしました
2<<24
(33554432) ランダム整数の入力データを使用
- 出力を表示しない (端末のスクロール パフォーマンスを測定したくない)
- 大まかなタイミングは
- STL のみのバージョンは実際には 12.6 秒でそれほど悪くはありません
- Arlen のヒントのおかげで、Karma/Qi テキスト バージョンは
18 秒 5.1秒で実行されました:)generate_delimited
- Karma/Qi バイナリ バージョン (big_dword) はわずか 1.4 秒 (約
12 倍、3 ~ 4 倍の速さ)
- Boost Serialization は約 0.8 秒 (バイナリの代わりにテキスト アーカイブを使用する場合は約 13 秒) でケーキを完成させます。