【问题标题】:Scope difference between MyClass(expr); and MyClass myObject(expr); [duplicate]MyClass(expr); 之间的范围差异;和 MyClass myObject(expr); [复制]
【发布时间】:2011-10-07 07:13:28
【问题描述】:

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

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++;

Edit2:啊,我现在明白了,除非我将我的对象绑定到一个变量,否则它会在计算表达式后被销毁。感谢你的帮助。

有人知道为什么 C++ 是这样写的吗?临时变量立即销毁有什么用?

【问题讨论】:

  • 我认为它们是相关的,但不是重复的。这个问题是关于MyClass(expr);MyClass myObject(expr); 之间的区别,答案是关于第一种情况的临时变量。而潜在的重复是专门询问临时工的生命周期。

标签: c++ object constructor scope


【解决方案1】:
{
    ScopedStat("Rendering");
    Render();
}

但是,这不起作用,因为编译器或其他东西可能有 优化了 ScopedStat 对象。报告的时间是一小部分 一毫秒,远不及渲染所需的时间。 我的问题是,为什么这种方式不起作用?这个对象没有得到吗 在作用域结束时销毁?

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

你将给它一个名字。


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

doFoo(ScopedStat("Rendering"));

只要调用doFoo,临时就可以活下去。

【讨论】:

    【解决方案2】:

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

    你必须为你的对象命名才能让它们一直存在到括号范围的末尾。

    ScopedStat stat("Rendering");
    

    【讨论】:

      【解决方案3】:

      您创建了一个临时对象,该对象立即超出范围,即下一行开始执行。以便在渲染之前完成启动和停止。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-26
        • 1970-01-01
        • 2020-12-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多