名称具有范围(编译时属性),而对象具有生命周期(运行时属性)。正确的?
我经常看到人们谈论“超出范围”的临时对象。但是由于临时对象没有名称,我认为在这种情况下谈论“范围”是没有意义的。临时对象的生命周期定义非常明确,与作用域无关。你会同意吗?
名称具有范围(编译时属性),
是的。我不会称其为财产思想。但基本上是的。
而对象有生命周期(运行时属性)。正确的?
变量分为三种。每种类型都具有与生命周期相关的不同属性。
注意:自动存储持续时间对象具有绑定到变量范围的生命周期。
我经常看到人们谈论“超出范围”的临时对象。
除非绑定到变量,否则临时变量会在表达式末尾被销毁。如果它们绑定到一个变量(一个 const 引用),那么它们的生命周期与变量相同。有时将其称为范围更容易,但从技术上讲,您是正确的。
但是由于临时对象没有名称,我认为在这种情况下谈论“范围”是没有意义的。
技术上是的。但我认为它只是让谈论它更容易。对我来说(虽然在技术上不正确)临时(未绑定)的范围是表达式。它比临时变量的生命周期更容易说。
临时对象的生命周期定义非常明确,与作用域无关。你会同意吗?
是的。但是谈论范围仍然感觉更自然(即使它在技术上不正确)。正如大多数人所理解的那样,您想要暗示什么。但是,当您开始谈论非常技术性的内容时,您应该使用正确的术语,而在这种情况下,范围是不正确的。
临时对象的生命周期与句法块几乎没有关系,但“范围”——作为一个词而不是一个技术术语——可以以其他方式使用。重要的问题是,当人们使用“范围”来指代临时对象时,您是否感到困惑。(从我的 POV 来看,你似乎不是。)
由于您正在谈论使用该术语与他人交流,因此这种交流非常重要。如果您通过编写标准文档来定义术语或试图在定义术语的上下文中解释此类文档,情况会有所不同。当然,解释 ISO 14882 将涉及与他人的沟通,因此在这种情况下,您只需要在必要时要求澄清。
使所有非标准通信都标准化会适得其反,并且在需要高精度时,在任何一种情况下都最好使用代码。出于这个原因,C++ 标准广泛使用示例。
再举一个例子,经常使用“调用构造函数”,但从技术上讲,您不能直接调用 ctor;相反,ctors 是对象初始化的一部分。这就是为什么有一个明确的 new 形式只是为了构造一个对象。(有趣的是,您可以直接调用析构函数。)但是,我希望在大多数情况下都能理解该短语,尽管我不提倡在标准上下文中使用它。
我见过人们说“一个对象超出范围”,当它意味着(用你的说法)“对象的生命周期在对象的名称超出范围时结束”。如果你使用那个简短的形式,很自然地说临时对象也超出了范围。
绑定到 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 的这篇文章:
通常,临时对象只持续到它出现的完整表达式的结尾。但是,C++ 特意指定将临时对象绑定到堆栈上的 const 引用会将临时对象的生命周期延长到引用本身的生命周期,从而避免常见的悬空引用错误。
临时对象确实有名称,尽管它只能由编译器引用。否则编译器将如何引用它们?仅仅因为一旦实例化就不能引用临时对象并不意味着编译器不能引用它。
f(Foo(), Bar());
编译器必须至少引用其中一个临时变量,即使您作为程序员不能引用它们中的任何一个。临时对象确实有一个范围。