我正在为非STL容器类型实现一个自定义迭代器,并遇到了以下行为,在这个阶段,对我来说似乎有些意外。
当您定义“空”dtor时,似乎会产生显着的性能损失?为什么?
为了尝试深入研究这个问题,我为std :: vector实现了一个简单的迭代器,这样我就可以直接将性能与标准的STL迭代器进行比较。为了公平测试,我只是从“vector.hpp”复制了一个简化的实现,并尝试添加一个额外的“空”dtor:
template <typename _Myvec>
class my_slow_iterator // not inheriting from anything!!
{
public :
_Myvec::pointer _ptr; // pointer to vector element
/* All of the standard stuff - essentially from "vector.hpp" */
/* An additional empty dtor */
~my_slow_iterator () {}
};
然后我修改了std :: vector,这样我可以让它返回我的新迭代器类型并使用以下内容进行基准测试 - 对2000000个随机整数的向量进行排序,平均三次运行:
std::vector vec;
// fill via rand();
int tt = clock();
std::sort(vec.begin(), vec.end());
tt = clock() - tt; // elapsed time in ms
我获得了以下结果(VS2010,发布版本,_ITERATOR_DEBUG_LEVEL 0等):
my_slow_iterator
:560 ms。my_slow_iterator
:900 ms。在这种情况下,空的dtor似乎导致减速约40%。
显然,如果dtor是空的那么为什么要这样,但是我期待像这样的简单“空”函数在编译时被内联和优化。如果情况并非如此,那么我想了解在这种类型的问题在更复杂的情况下会产生分歧时会发生什么。
编辑:使用O2优化编译。
编辑:进一步挖掘,似乎复制ctor发生了类似的效果。最初(在上面的测试中)my_slow_iterator
没有定义copy-ctor,因此使用编译器生成的默认值。
如果我定义了以下copy-ctor(它不会超出我期望编译器生成的那个):
my_slow_iterator (
const my_slow_iterator<_Myvec> &_src
) : _ptr(_src._ptr) {}
我看到与上述相同的测试结果如下:
my_slow_iterator
,删除了dtor,copy-ctor包括:690ms my_slow_iterator
,包括dtor,copy-ctor包括:980ms 这是一个进一步(虽然没有那么激烈)的表现。
为什么/如何使编译器默认功能更加高效?用户定义的ctor / dtor是否隐含地在后台做某事??
答案 0 :(得分:1)
我记得在Linux上遇到过与GCC(-O3)类似的东西。尽管是空的并且在头文件中,但是发出了用户定义的析构函数的代码,而编译器生成的默认析构函数没有产生指令。这使我困惑,最终我使代码工作时没有明确的析构函数(虽然代价是能够在其中添加assert()
,这就是为什么空的一个是可取的 - 它不是空的debug build)。