2012-06-22 38 views
2

只是一个问题,为我自己的好奇心。我多次听说,在编写方法时最好使用复制/销毁范例。所以,如果你有这样的方法:编译器是否可以在循环中生成对象的内联方法?

OtherClass MyClass::getObject(){ 
    OtherClass returnedObject; 
    return returnedObject; 
} 

据称,编译器将内联基本方法和调用getObject方法的堆栈上生成的类优化此。我不知道怎么会在一个循环,工作像这样

for(int i=0; i<10; i++){ 
    list.push_back(myClass.getObject()); 
} 

将编译器放OtherClass 10个实例在栈上,因此它可以内联这个方法,避免复制和破坏,将在未优化的代码发生?怎么样这样的代码:

while(!isDone){ 
    list.push_back(myClass.getObject()); 
    //other logic which decides rather or not to set isDone 
} 

在这种情况下,编译器可能无法知道getObject多少次会被调用,所以推测它可以预先分配给任何堆栈,所以我的假设是没有内联完成并且每次调用方法我都将支付全部复制费用OtherObject

我意识到所有的编译器都不一样,而这取决于编译器相信这个代码是最优的。我只是泛泛而谈,大部分汇编最有可能如何回应?我很好奇这种优化是如何完成的。

+0

认为内联为代码复制+粘贴。如果可以复制/粘贴,则可以内联。编译器是否会在特定情况下做到这一点是另一回事。 – Mysticial

+1

'otherClass returnedObject();'构造什么都不做 - 不会创建任何对象 – sharptooth

+0

@sharptooth - 编辑删除错误,因为这对他的问题并不重要。 –

回答

2
for(int i=0; i<10; i++){ 
    list.push_back(myClass.getObject()); 
} 

将编译器放在堆栈上OtherClass的10个实例,因此它可以内联这个方法,避免复制和破坏,将在未优化的代码发生?

它不需要需要把10个实例放在堆栈上,以避免复制和销毁...如果在有或没有返回值优化的情况下返回一个对象的空间,那么它可以重复使用该空间10次 - 每次通过列表push_back从同一个堆栈空间复制到一些新的堆分配的内存。

它甚至会在编译器权限内分配新内存并安排myClass.getObject()直接在内存中构造对象。另外,如果优化器选择展开循环,它可能会调用myClass.getObject()10次 - 即使存在一些重叠或并行 - 如果它能以某种方式说服自己产生相同的总体结果。在这种情况下,它确实需要10个返回对象的空间,并且再次由编译器决定,无论它是堆栈还是通过奇迹般的巧妙优化,直接存储在堆内存中。

实际上,我希望编译器需要从堆栈复制到堆 - 我非常怀疑任何主流编译器的聪明程度足以在堆内存中安排直接构建。虽然循环展开和RVO是常见的优化。但是,即使两者都开始了,我也希望每次调用getObject都可以在堆栈中串行构造一个结果,然后将结果复制到堆中。

如果你想“知道”,写一些代码来测试你自己的编译器。你可以让构造函数写出“this”指针值。

怎么样这样的代码:

while(!isDone){ 
    list.push_back(myClass.getObject()); 
    //other logic which decides rather or not to set isDone 
} 

更复杂和更地道的代码,就越有可能的编译器编写者已经能够和困扰,以优化它。在这里,你甚至没有向我们展示我们可以推测的复杂度。尝试它为您的编译器和优化设置,并参阅....

1

一般来说,优化编译器可以使任何任何改变你的代码,只要产生的程序的行为没有明显改变。这包括inline ing函数(或不),即使该函数没有被程序员标记为inline

0

编译器唯一需要关心的是程序行为。如果优化保持程序逻辑和数据不变,则优化为legal。进入的内容(所有可能的程序输入)必须以与没有最佳化相同的方式出来(所有可能的程序输出)。

这个特定的优化是否可能(它当然是,是否是一个实际的优化是不同的事情!)取决于目标平台指令集,如果它是可行的实现它。

相关问题