我是粉丝STL算法,因此我经常在工作中使用许多STL算法。但是,...
考虑以下简单示例: //编译器:Visual Studio 2010 Sp1。 Cpu:i5 3300MG。
struct FileInfo
{
std::string filename_;
std::string filename()const { return filename_;}
};
//works with 1000 FileInfos, Elapsed: 127.947 microseconds
std::string sumof_filenames_1(std::vector<FileInfo> const& fv )
{
std::string s;
for( std::size_t ix = 0u; ix < fv.size(); ++ix) s += fv[ix].filename();
return s;
}
//Elapsed: 7430.138 microseconds
std::string sumof_filenames_2(std::vector<FileInfo> const& fv )
{
struct appender{
std::string operator()(std::string const& s, FileInfo const& f)const
{ return s + f.filename(); }
};
return std::accumulate( std::begin(fv), std::end(fv), std::string(), appender() );
}
//Elapsed: 10729.381 microseconds
std::string sumof_filenames_3(std::vector<FileInfo> const& fv )
{
struct appender{
std::string operator()(std::string & s, FileInfo const& f) const
{ return s+= f.filename(); }
};
std::accumulate( std::begin(fv), std::end(fv), std::string(), appender() );
}
问:如何使用STL算法优化sum_of_filenames,例如std :: accumulate或其他任何算法,以及如何实现appender仿函数?
测试:主要功能:
int main()
{
enum{ N = 1000* 1 };
srand(14324);
std::vector<FileInfo> fv;
fv.reserve(N);
for(std::size_t ix = 0; ix < N; ++ix)
{
FileInfo f;
f.m_Filename.resize( static_cast< int > ( rand() * 256 / 32768 ) + 15 , 'A');
//for( std::size_t iy = 0; iy < f.m_Filename.size(); ++iy)
// f.m_Filename[iy] = static_cast<char>( rand() * 100 / 32768 + 28 );
fv.push_back( f );
}
LARGE_INTEGER freq, start, stop;
QueryPerformanceFrequency(&freq);
{
QueryPerformanceCounter(&start);
std::string s = sumof_filenames_1(fv);
QueryPerformanceCounter(&stop);
double elapsed = (stop.QuadPart - start.QuadPart)* 1000.0 / (double)(freq.QuadPart) * 1000.0;
printf("Elapsed: %.3lf microseconds\n", elapsed);
printf("%u\n", s.size());
}
{
QueryPerformanceCounter(&start);
std::string s = sumof_filenames_2(fv);
QueryPerformanceCounter(&stop);
double elapsed = (stop.QuadPart - start.QuadPart)* 1000.0 / (double)(freq.QuadPart) * 1000.0;
printf("Elapsed: %.3lf microseconds\n", elapsed);
printf("%u\n", s.size());
}
{
QueryPerformanceCounter(&start);
std::string s = sumof_filenames_3(fv);
QueryPerformanceCounter(&stop);
double elapsed = (stop.QuadPart - start.QuadPart)* 1000.0 / (double)(freq.QuadPart) * 1000.0;
printf("Elapsed: %.3lf microseconds\n", elapsed);
printf("%u\n", s.size());
}
答案 0 :(得分:2)
尝试估算以下功能
std::string sumof_filenames_3(std::vector<FileInfo> const& fv )
{
struct appender{
std::string & operator()(std::string & s, FileInfo const& f) const
{ return s+= f.filename(); }
};
return std::accumulate( std::begin(fv), std::end(fv), std::string(), appender() );
}
并使用lambda表达式
std::string sumof_filenames_3(std::vector<FileInfo> const& fv )
{
return std::accumulate( std::begin(fv), std::end(fv), std::string(),
[]( std::string &s, FileInfo const& f ) -> std::string &
{
return s += f.filename();
} );
}
还要估算以下循环
std::string sumof_filenames_1(std::vector<FileInfo> const& fv )
{
std::string::size_type n = 0;
for each ( FileInfo const& f in fv ) n += f.filename().size();
std::string s;
s.reserve( n );
for( std::size_t ix = 0u; ix < fv.size(); ++ix) s += fv[ix].filename();
return s;
}
对以下列方式定义的结构进行相同的估计
struct FileInfo
{
std::string filename_;
const std::string & filename()const { return filename_;}
};
答案 1 :(得分:2)
我想起了for_each
:
std::string sumof_filenames(std::vector<FileInfo> const& fv )
{
std::string s;
std::for_each(std::begin(fv), std::end(fv), [&s](const FileInfo& f){s += f.filename();});
return s;
}
或没有lamba
struct Appender
{
std::string& m_s;
Appender(std::string& s):m_s(s){};
void operator()(const FileInfo& f) const
{ s += f.filename(); }
};
std::string sumof_filenames(std::vector<FileInfo> const& fv )
{
std::string s;
std::for_each(std::begin(fv), std::end(fv), Appender(s)});
return s;
}