0

例如,假设我正在循环一个指针向量以检查多个对象并对它们执行操作。我可以执行以下任一操作。

方法一:

std::vector< Object* >::iterator it;
Object* o;
for (it = objects.begin(); it != objects.end(); ++it)
{
    o = (*it)
    if(o->GetActive())
    {
        o->method;
        o->method2;
        o->method3;
        //etc...
    }
 }

方法二:

std::vector< Object* >::iterator it;
for (it = objects.begin(); it != objects.end(); ++it)
{
    if((*it)->GetActive())
    {
        (*it)->method;
        (*it)->method2;
        (*it)->method3;
        //etc...
    }
 }

从我所见,方法 1 具有更容易的可读性,因为取消引用语法通常会使可读性复杂化,尤其是当您执行以下操作时:

if((*o)->CheckValue((*c)))

但是创建局部变量会更容易阅读:

if(o->CheckValue(c))

但是您正在创建额外的变量,这会增加内存成本,对吗?

性能上的差异是什么?

4

3 回答 3

3

优化编译器可能会使它们相同。有时分配给变量以获得更好的可读性是很好的。如果容器不包含指针,您可以改用引用:

std::vector< Object >::iterator it;
for (it = objects.begin(); it != objects.end(); ++it)
{
    const Object &o = (*it)
    if(o.GetActive())
    {
        o.method();
        o.method2();
        o.method3();
        //etc...
    }
 }

编辑:正如 Raymond 在评论中指出的那样,如果方法可能会改变有问题的对象,编译器将无法进行某些优化。解决这个问题的方法是尽可能使用const,所以我改变了我的例子以在实践中展示它。如果你这样做,你就不能调用对象上没有标记的方法const

于 2013-09-23T02:12:17.413 回答
1

事实上,我会选择另一种语法,这使得选择无关紧要:

for (Object* o : objects)
{
  // ... body
}
于 2013-09-23T07:55:53.767 回答
0

除非你volatile周围有对象,否则在处理本地对象时,它主要归结为可读性,因为编译器通常会自己处理这些东西。

在您的特定情况下,*it是编译器必须执行的操作其结果将以寄存器结尾;因此,几乎可以肯定编译器无论如何都会将结果留在寄存器中以供下次使用,从而“隐式”创建您的o变量。换句话说,归结为汇编,该变量自行产生。

相反,如果编译器无法简单地证明it在取消引用之间没有修改(例如,如果指向它的指针 - 或指向objects- 被传递,或者它是非本地的),或者如果它被明确指示避免这种优化,这是一种不同的情况(通过volatile关键字)。

于 2013-09-23T02:12:05.220 回答