您只复制 4 个字符(取决于系统的指针宽度)。这将使超过 4 个字符的数字非空终止,从而导致 atoi 输入中的字符串失控
sizeof(str.c_str()) //i.e. sizeof(char*) = 4 (32 bit systems)
应该
str.length() + 1
或者字符不会被空终止
仅限 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;
}
您可以使用 atoi/itoa 和一些调整在普通 C 中更快地完成它,但我认为如果您需要速度,您应该使用二进制传输(请参阅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);
提升序列化
在二进制模式下使用 Boost Serialization 可以达到最佳性能:
#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 秒时还不错
- Karma/Qi 文本版本
在 18s 5.1s中运行,感谢 Arlen 的提示generate_delimited
:)
- Karma/Qi 二进制版本 (big_dword) 仅需 1.4 秒(大约
12倍 3-4倍的速度)
- Boost Serialization 大约需要 0.8 秒(或者当替换文本存档而不是二进制文件时,大约需要 13 秒)