MyClass(expr)之间的范围差异;和MyClass myObject(expr);

时间:2011-07-17 21:30:48

标签: c++ object constructor scope

我有一个统计管理器,它通过测量方法执行所需的时间来检查我的应用程序性能。它的用法是这样的:

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 ++?如果临时变量被立即销毁,它有什么用?

3 个答案:

答案 0 :(得分:4)

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

然而,这不起作用,因为编译器或其他东西也许   优化了ScopedStat对象。报告的时间是一小部分   一毫秒,远不及渲染时间。   我的问题是,为什么这种方式不起作用?这个对象不会得到   在范围的最后被毁?

你没有创建一个恰好没有名字的普通变量。您正在创建临时,并且它在声明它的full-expression末尾不再存在。 (也就是说,在调用Render()之前,ScopedStat已经来去匆匆。)

给它命名。


要回答您的最后一个问题,当您执行以下操作时,这非常有意义:

doFoo(ScopedStat("Rendering"));

只要对doFoo的呼叫恰到好处,临时就会存在。

答案 1 :(得分:3)

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

您必须为对象命名,直到括号范围结束。

ScopedStat stat("Rendering");

答案 2 :(得分:1)

您已创建一个临时超出范围的临时对象,即下一行开始执行时。所以在渲染之前完成开始和停止。