我有一个统计管理器,它通过测量方法执行所需的时间来检查我的应用程序性能。它的用法是这样的:
myStatManager.StartStat("Rendering");
Render();
myStatManager.StopStat("Rendering");
输出到屏幕将告诉我该方法花了多长时间。
为方便起见,我编写了一个虚拟对象,在创建和销毁对象时调用这两个方法。这使我可以使用C ++范围规则,只需输入一次stat跟踪行,而不是上面两次。
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 ++;
Edit2:啊,我现在明白了,除非我将我的对象绑定到一个变量,否则在计算表达式后它会被销毁。感谢你的帮助。
有谁知道为什么用这种方式编写C ++?如果临时变量被立即销毁,它有什么用?
答案 0 :(得分:4)
{ ScopedStat("Rendering"); Render(); }
然而,这不起作用,因为编译器或其他东西也许 优化了ScopedStat对象。报告的时间是一小部分 一毫秒,远不及渲染时间。 我的问题是,为什么这种方式不起作用?这个对象不会得到 在范围的最后被毁?
你没有创建一个恰好没有名字的普通变量。您正在创建临时,并且它在声明它的full-expression
末尾不再存在。 (也就是说,在调用Render()
之前,ScopedStat
已经来去匆匆。)
你 给它命名。
要回答您的最后一个问题,当您执行以下操作时,这非常有意义:
doFoo(ScopedStat("Rendering"));
只要对doFoo
的呼叫恰到好处,临时就会存在。
答案 1 :(得分:3)
如果您不使用对象的标识符,它将成为临时对象,并在其所属的表达式结束后被销毁。换句话说,它具有单个表达式的范围。
您必须为对象命名,直到括号范围结束。
ScopedStat stat("Rendering");
答案 2 :(得分:1)
您已创建一个临时超出范围的临时对象,即下一行开始执行时。所以在渲染之前完成开始和停止。