临时对象有范围吗?

10

变量名具有作用域(编译时属性),而对象具有生命周期(运行时属性)。对吗?

我经常看到人们谈论临时对象“超出作用域”的情况。但由于临时对象没有名称,因此在这种情况下谈论“作用域”是没有意义的。临时对象的生命周期非常清晰地定义,与作用域无关。您同意吗?

5个回答

10

变量有作用域(编译时属性),

没错。虽然我不会称之为属性,但基本上是这样。

而对象有生命周期(运行时属性)。对吗?

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

  • 自动存储期:
  • 静态存储期
  • 动态存储期

注意:自动存储期对象的生命周期绑定到变量的作用域。

我经常看到人们谈论临时对象“超出作用域”的问题。

除非绑定到变量,否则临时对象在表达式结束时被销毁。如果它们绑定到变量(一个const引用),那么它们具有与变量相同的寿命。有时候只是更容易把这个称为作用域,但从技术上讲你是正确的。

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

从技术上讲是对的。但我认为这样更容易谈论。对我来说(虽然从技术上讲不正确),临时变量(未绑定)的作用域是表达式。这比说临时变量的寿命更容易。

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

是的。但在这种情况下谈论作用域仍然更自然(即使从技术上讲不正确)。因为大多数人都能理解你试图暗示什么。但当你深入讨论非常技术性的问题时,应该使用正确的术语,而在这种情况下,作用域是不正确的。


4
临时对象的生命周期与语法块没有太大关系,但是“作用域”——作为一个词而不是技术术语——可以用其他方式。重要的问题是当人们用“作用域”来指代临时对象时,你是否感到困惑。(从我的角度来看,似乎你并没有。)
由于您在与他人交流时使用该术语,因此该交流才是真正重要的。如果您正在编写标准文档或尝试在定义的术语上下文中解释这样的文档,则情况将有所不同。当然,在解释ISO 14882时,涉及与他人的交流,因此在那种情况下,您只需在必要时请求澄清即可。
让所有非标准化交流都成为标准化交流是低效的,通常最好在需要高精度时使用代码。C++标准经常使用示例说明这一点。
例如,“调用构造函数”经常被使用,但从技术上讲,您不能直接调用构造函数;相反,构造函数是对象初始化的一部分。这就是为什么有显式形式的new仅用于构建对象。(有趣的是,您可以直接调用析构函数。)但是,我希望该短语在大多数情况下都能得到理解,尽管我不赞成在标准化上下文中使用它。

1
我看到有人说“一个对象超出了作用域”,而实际上它的意思是“当对象的名称超出作用域时对象的生命周期结束”。如果您使用这种缩写形式,自然而然地会说临时对象也会超出作用域。

1
但是临时对象在创建它的词法上下文中没有名称,因此没有名称会超出作用域 :) - fredoverflow
显然不是。关键是,“对象超出作用域”的术语通常适用于任何生命周期没有被delete pObject明确终止的对象。 - MSalters

0

临时对象确实有名称,尽管只能由编译器引用。否则编译器怎么引用它们呢?仅仅因为你在实例化后无法引用临时对象并不意味着编译器不能引用它。

f(Foo(), Bar());

编译器必须引用至少一个临时变量,即使你作为程序员不能引用它们中的任何一个。临时对象确实有作用域。

按照这个逻辑,数组的每个成员都需要一个名称。但我们知道编译器可以通过地址引用数组的成员。临时变量也可以使用相同的方法:编译器知道它们的地址和类型,就足够了。 - MSalters

0

将一个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引用会延长临时对象的寿命,直到引用本身的寿命结束,并因此避免了普遍的悬空引用错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接