我有一个函数,它接收一个字符列表并生成下一个字典排列。为了好玩,我尝试将代码概括为使用迭代器,以及能够生成更多不同类型的排列。
template<typename ITER>
bool nextPermutation(ITER start, ITER end, std::random_access_iterator_tag)
{
for(ITER i = end-1; i != start; --i)
{
if(*(i-1) < *i)
{
// found where can be swapped
for(ITER j = end-1; j != (i-1); --j)
{
if(*(i-1) < *j)
{
// found what to swap with
auto temp = *j;
*j = *(i-1);
*(i-1) = temp;
// put everything from i on into "sorted" order by reversing
for(ITER k = end-1; k > i; --k,++i)
{
temp = *k;
*k = *i;
*i = temp;
}
return true;
}
}
}
}
return false;
}
但是,我遇到的问题是,当我不使用原始指针时,代码的性能会明显变慢。这是我的试验台:
template<typename ITER>
bool nextPermutation(ITER start, ITER end, std::random_access_iterator_tag);
template<typename ITER>
bool nextPermutation(ITER start, ITER end)
{
return nextPermutation(start, end, std::iterator_traits<ITER>::iterator_category());
}
#define USE_VECTOR
int main(void)
{
bool hasNext = true;
#ifdef USE_VECTOR
std::vector<char> c;
for(char i = '0'; i <= '9'; ++i)
{
c.push_back(i);
}
for(size_t i = 0; i < 999999 && hasNext; ++i)
{
hasNext = nextPermutation(c.begin(), c.end());
}
#else
char c[] = "0123456789";
size_t LENGTH = 10;
for(size_t i = 0; i < 999999 && hasNext; ++i)
{
hasNext = nextPermutation(c, c+LENGTH);
}
#endif
std::cout << "done" << std::endl;
std::cin.ignore();
return 0;
}
定义USE_VECTOR
时,运行此测试装备需要大约20秒。当我取消定义它时,代码运行不到一秒钟(我没有写任何时序代码,但足以说明性能有非常显着的差异。)
现在我的问题是我在哪里使用迭代器(std :: string iterator,std :: vector iterator等)与原始指针相比会产生如此巨大的性能损失?
答案 0 :(得分:7)
如果没有优化,由于迭代器调试繁重(_ITERATOR_DEBUG_LEVEL
在调试模式下默认为2,即完全调试),代码在我的机器上也很慢。
但是,使用/02
时,迭代器调试将被完全禁用,代码将在控制台窗口显示之前完整执行。
在这里,您有一个调试使事情变得更慢但更安全的一个很好的例子。 :)
答案 1 :(得分:1)
在我的方框中,这些是时间,从采取上述时间,删除cin.ignore()
,并使用以下标杆进行基准测试:
$ g++-4.6 -O4 -DUSE_VECTOR -std=gnu++0x t.cpp -o t
$ time for a in $(seq 1 1000); do ./t; done > /dev/null
真正的0m10.145s 用户0m7.204s sys 0m1.088s
$ g++-4.6 -O4 -std=gnu++0x t.cpp -o t
$ time for a in $(seq 1 1000); do ./t; done > /dev/null
真正的0m7.693s 用户0m3.280s sys 0m0.984s
**如果你问我**,那里没有令人震惊的差异
现在为了一拳:
$ g++-4.6 -O0 -std=gnu++0x t.cpp -o t
$ time for a in $(seq 1 1000); do ./t; done > /dev/null
真正的0m29.540s 用户0m27.294s sys 0m0.976s