为什么在范围块结束之前,未命名的C ++对象会被破坏?

时间:2010-02-19 18:51:28

标签: c++ scope destructor

以下代码打印一,二,三。对于所有C ++编译器来说,这是否合乎需要?


class Foo
{
      const char* m_name;
public:
      Foo(const char* name) : m_name(name) {}
      ~Foo() { printf("%s\n", m_name); }
};

void main()
{
      Foo foo("three");
      Foo("one");   // un-named object
      printf("two\n");
}

5 个答案:

答案 0 :(得分:36)

临时变量一直存在,直到创建它的完整表达式结束。你的结尾以分号结束。

这是在12.2 / 3:

  

临时对象在评估全表达式(1.9)的最后一步时被销毁,该表达式(词法上)包含创建它们的点。

您的行为有保障。

有两个条件,如果满足,将延长临时的生命周期。第一个是它是一个对象的初始化器。第二个是引用绑定到临时引用。

答案 1 :(得分:12)

管理临时对象生命周期的规则与范围的概念无关。范围是名称的属性,临时对象没有名称。换句话说,临时对象没有范围。

大多数情况下,临时对象的生命周期在创建该对象的完整表达式的末尾结束,这是您在实验中观察到的。这是一般规则,有一些例外。主要的一点是,如果您立即附加对临时对象的引用,对象的生命周期将被扩展以匹配引用的生命周期

const Foo &rfoo = Foo("one");

只要rfoo生命,上述临时活动就会存在。

答案 2 :(得分:6)

像这样的临时对象的范围只是一行。考虑一下,你不能再在行结束后引用它,那么为什么这个对象会一直存在呢?

如果不是这种情况,编译器将无法在函数调用中优化临时对象。

答案 3 :(得分:3)

是的,这是理想的。

Foo foo("three")创建一个普通对象,当范围结束时将被销毁。

Foo("one")创建一个临时对象,在指令[1]末尾被销毁。为什么?因为在指令结束后你无法访问它。

[1]故意简化:我应该说序列点

答案 4 :(得分:0)

因为标准委员会蠢蠢欲动。这样做是因为他们选择让它做到这一点。它的定义是这样做的。它应该被视为一个匿名实例,其范围与命名时相同。从实例化到块结束。显然他们认为唯一的用途是将临时工具传递到函数中,在函数中它被推入堆栈并在函数调用结束时弹出堆栈...

仍应将未命名的对象推入堆栈并保留在堆栈中,直到块结束,从而在预期时将其从堆栈中弹出。在单个语句中构造和销毁对象是没有意义的。我想看一个实际有用的单个实例/案例。如果它在块的持续时间内没有停留在范围内,那么它肯定是一个错误,并且至少应该产生警告。