【问题标题】:Do temporary objects have scope?临时对象有范围吗?
【发布时间】:2010-11-24 14:08:33
【问题描述】:

名称具有范围(编译时属性),而对象具有生命周期(运行时属性)。对吧?

我经常看到人们谈论临时对象“超出范围”。但是由于临时对象没有名称,我认为在这种情况下谈论“范围”是没有意义的。临时对象的生命周期为very clearly defined,与作用域无关。你同意吗?

【问题讨论】:

    标签: c++ object scope temporary lifetime


    【解决方案1】:

    名称具有范围(编译时属性),

    是的。我不会称其为财产思想。但基本上是的。

    虽然对象有生命周期(运行时属性)。对吧?

    有三种类型的变量。每种类型都有与生命周期相关的不同属性。

    • 自动存储时长:
    • 静态存储持续时间
    • 动态存储持续时间

    注意:自动存储持续时间对象具有绑定到变量范围的生命周期。

    我经常看到人们谈论临时对象“超出范围”。

    除非绑定到变量,否则临时变量会在表达式末尾被销毁。如果它们绑定到一个变量(一个 const 引用),那么它们的生命周期与变量相同。有时将其称为范围更容易,但从技术上讲,您是正确的。

    但由于临时对象没有名称,我认为在这种情况下谈论“范围”是没有意义的。

    技术上是的。但我认为它只是让谈论它更容易。对我来说(虽然在技术上不正确)临时(未绑定)的范围是表达式。它比临时变量的生命周期更容易说。

    临时对象的生命周期定义非常明确,与作用域无关。你同意吗?

    是的。但是谈论范围仍然感觉更自然(即使它在技术上不正确)。正如大多数人所理解的那样,您想要暗示什么。但是当你开始谈论非常技术性的东西时,你应该使用正确的术语,而在这种情况下范围是不正确的。

    【讨论】:

      【解决方案2】:

      临时对象的生命周期与句法块几乎没有关系,但“范围”——作为一个词而不是一个技术术语——可以以其他方式使用。重要的问题是,当人们使用“范围”来指代临时对象时,您是否感到困惑。 (从我的 POV 看来,你不是。)

      既然您是在谈论使用该术语与他人交流,那么交流才是真正重要的。如果您通过编写标准文档来定义术语或尝试在定义术语的上下文中解释此类文档,情况会有所不同。当然,解释 ISO 14882 将涉及与他人的沟通,因此在这种情况下,您只需要在必要时要求澄清即可。

      让所有非标准的通信都成为标准的会适得其反,当需要高精度时,通常最好在任何一种情况下使用代码。出于这个原因,C++ 标准广泛使用示例。

      再举一个例子,经常使用“调用构造函数”,但从技术上讲,您不能直接调用 ctor;相反,ctors 是对象初始化的一部分。这就是为什么有一个明确的 new 形式只是为了构造一个对象。 (有趣的是,您可以直接调用析构函数。)但是,我希望在大多数情况下都能理解该短语,尽管我不提倡在标准上下文中使用它。

      【讨论】:

        【解决方案3】:

        我见过人们说“一个对象超出范围”,当它意味着(用你的话说)“对象的生命周期在对象的名称超出范围时结束”。如果你使用那个简短的形式,很自然地说临时对象也超出了范围。

        【讨论】:

        • 但是一个临时对象在它被创建的词法上下文中没有名字,所以没有名字可以脱离范围:)
        • 显然不是。关键是,术语“超出范围的对象”通常适用于生命周期未由delete pObject 明确终止的任何对象。
        【解决方案4】:

        临时对象确实有名称,尽管它只能由编译器引用。否则编译器将如何引用它们?实例化后不能引用临时对象并不意味着编译器不能引用它。

        f(Foo(), Bar());
        

        编译器必须至少引用其中一个临时变量,即使您作为程序员不能引用其中任何一个。临时对象确实有范围。

        【讨论】:

        • 按照这个逻辑,数组的每个成员都需要一个名称。然而我们知道编译器可以通过地址引用数组的成员。临时对象也可以这样工作:编译器知道它们的地址和类型,这就足够了。
        【解决方案5】:

        绑定到 const 引用会将临时对象的生命周期延长到引用的生命周期,因此在某种意义上,它确实在这种特殊情况下与范围有关:

        std::string foo();
        
        int main()
        {
            // Lifetime of the temporary returned by foo is indeed the scope of bar
            const std::string &bar = foo();
        }
        

        请参阅 Herb Sutter 的 this article

        通常,临时对象会持续 直到完整的结束 它出现的表达式。 但是,C++ 故意指定 将临时对象绑定到 对栈上的 const 的引用 延长使用寿命 暂时的生命周期 引用自身,从而避免了什么 否则将是一个常见的 悬空引用错误。

        【讨论】:

          猜你喜欢
          • 2012-04-26
          • 2015-03-03
          • 2011-03-20
          • 2022-06-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-09-29
          相关资源
          最近更新 更多