使用方法1与方法2的优缺点是什么?
方法1:
for ( std::vector<MyObject*>::iterator it = my_objects.begin(); it != my_objects.end(); ++it )
{
Vector2 temp_position = (*it)->GetPosition();
// do something...
}
方法2:
Vector2 temp_position; // I do NOT need scope for this object outside of the loop.
for ( std::vector<MyObject*>::iterator it = my_objects.begin(); it != my_objects.end(); ++it )
{
temp_position = (*it)->GetPosition();
// do something...
}
理论上,方法2的性能优于方法1,因为每次循环都不需要重新创建temp_position
变量。但是,我记得读过编译器会优化它们是相同的。
方法1更好,因为temp_position
没有不必要的范围。
答案 0 :(得分:2)
如果我们忽略编译器执行的任何优化,则每个版本调用的函数之间存在具体差异。
在方法1中,由于您在循环内部创建了向量,因此对于循环的每次迭代,它的构造函数将被调用一次(特别是其复制构造函数),并且它的析构函数将被调用一次。因此,粗略的成本是N个复制构造函数调用+ N个析构函数调用。
在方法2中,由于向量已存在于for循环中,因此将调用其复制赋值运算符。所以它的构造函数被调用一次,它的析构函数被调用一次,并且它的复制赋值运算符被调用了N次。粗略的成本是1个复制构造函数调用+ 1个析构函数调用+ N个复制赋值操作符调用。
他们最终在工作量方面大致相似。每次调用复制赋值运算符都需要分配一个数组并释放另一个数组;另一方面,复制构造函数调用分配一个数组,而析构函数释放一个数组。
我更喜欢方法1,因为它更接近地反映了你想要说的内容 - 向量确实是临时的,并且不需要存在于循环范围之外。
答案 1 :(得分:1)
“过早优化是所有邪恶的根源。” - Etienne de Martel
阿门。然而,我会错误地放置我的光环一秒钟然后说,即使编译器可能会优化该循环,甚至可能完全解除它在堆栈上的分配成本与你在那里进行的所有其他复制和分配无关。
我会像下面那样编写这个循环,即使编译器可能仍然可以使用它并在当天结束时做任何事情。
const std::vector<MyObject*>::const_iterator end(my_objects.cend());
for (std::vector<MyObject*>::const_iterator it(my_objects.cbegin()); it != end; ++it)
{
Vector2 temp_position((*it)->GetPosition());
// do something...
}