gprof
输出。我在代码中使用了deques、std::vector
和std::move
。
Flat profile:
Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls s/call s/call name
10.70 0.78 0.78 411724776 0.00 0.00 __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >::operator*() const
5.97 1.22 0.44 114087996 0.00 0.00 __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >::operator--()
5.90 1.65 0.43 256602502 0.00 0.00 __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >::base() const
5.90 2.08 0.43 197352626 0.00 0.00 std::remove_reference<int&>::type&& std::move<int&>(int&)
5.76 2.50 0.42 20556 0.00 0.00 void std::__move_merge_adaptive<int*, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__ops::_Iter_less_iter>(int*, int*, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__ops::_Iter_less_iter)
5.49 2.90 0.40 139505351 0.00 0.00 __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >::operator++()
这些函数是标准库的实现细节。由于您正在进行评测,因此希望在编译器中启用优化,因为除此之外,编译器基本上不关注如何使程序快速运行,而只是试图使其易于调试。一旦您启用了优化,您应该会看到这些函数消失,因为编译器意识到它们可以内联,从而消除了函数调用开销。
我希望Vaughn是对的,但根据我的经验,这并不总是有效的。事实上,从我所看到的情况来看,它几乎从不起作用。由于在调试构建中,您会失去对代码的可见性,因此程序员倾向于假设这些东西是内联的,而很可能不是内联的。一种检查方法是在DEBUG构建中打开优化,并检查生成的反汇编代码。
编译器往往无法弄清楚程序员的意图,所以它坚持什么是安全的。例如,程序员可能知道数组索引在数组边界内,甚至是常量,但这并不意味着编译器可以弄清楚。
当您使用标准库模板时,这是一个问题。我知道人们被鼓励使用它们,因为他们会发现初级编程错误,但你为它们付出的代价不会消失。