2011-07-17 36 views
2

我有一个统计管理器,通过测量执行方法所需的时间来检查我的应用程序性能。它的用法如下:MyClass(expr)之间的作用域差异;和MyClass myObject(expr);

myStatManager.StartStat("Rendering"); 
Render(); 
myStatManager.StopStat("Rendering"); 

输出到屏幕会告诉我该方法花了多长时间。

为了方便起见,我写了一个虚拟对象,在对象被创建和销毁时调用这两个方法。这使我可以使用C++范围规则来处理我的优势,只需输入一次统计跟踪行而不是上面的两次。

class ScopedStat 
{ 
    string label; 
    ScopedStat(string inLabel): label(inLabel) { myStatManager.StartStat(label); } 
    ~ScopedStat() { myStatManager.StopStat(label); } 
} 

预期的用法如下:

{ 
    ScopedStat("Rendering"); 
    Render(); 
} 

然而,这不起作用,因为也许是编译器什么的优化了ScopedStat对象了。所报告的时间仅为毫秒的几分之一,远不及应该呈现的时间。我的问题是,为什么这种方式不起作用?这个对象不会在范围的末尾被销毁吗?

编辑:我已经找到了解决办法:

{ 
    ScopedStat ss("Rendering"); 
    Render(); 
} 

这按预期工作 - 对象得到仅在大括号的结束时被销毁。虽然,我仍然想知道为什么。

注意:使用Microsoft Visual Studio 2008 C++;

编辑2:啊,我现在明白了,除非我将我的对象绑定到变​​量,否则在表达式评估之后它会被销毁。感谢你的帮助。

有谁知道为什么C++是这样写的?什么用途是一个临时变量,如果它立即被破坏?

+0

我认为他们是相关但不重复。这个问题关于'MyClass(expr);'和'MyClass myObject(expr)'之间的区别,答案是关于第一种情况的临时变量。而潜在的重复是特别要求关于临时性的生命周期。 – TooTone

回答

1

您已经创建了一个超出范围的临时对象,也就是下一行开始执行时。以便在渲染之前完成启动和停止。

3

如果您不使用对象的标识符,它将变为临时对象并在其所属的表达式结束后被销毁。换句话说,它具有单一表达的范围。

您必须为您的对象命名直到括号范围的末尾。

ScopedStat stat("Rendering"); 
4
{ 
    ScopedStat("Rendering"); 
    Render(); 
} 

然而,这不起作用,因为也许是编译器或某物 优化ScopedStat对象了。报告的时间是几分之一毫秒的几分之一,几乎不需要渲染。 我的问题是,为什么这种方式不起作用?这个对象是否在范围的最后被销毁了 ?

您没有创建一个正常的变量,只是碰巧没有名字。您正在创建一个临时,并且它在宣布它的full-expression的末尾不再存在。(也就是说,被调用Render()前,ScopedStat来了又走了。)

给它一个名字。


要回答你的最后一个问题,这使得当你做这样的事情非常有意义:

doFoo(ScopedStat("Rendering")); 

临时生活,只要不以doFoo通话是恰到好处。

相关问题