以下代码打印一,二,三。对于所有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");
}
答案 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)
因为标准委员会蠢蠢欲动。这样做是因为他们选择让它做到这一点。它的定义是这样做的。它应该被视为一个匿名实例,其范围与命名时相同。从实例化到块结束。显然他们认为唯一的用途是将临时工具传递到函数中,在函数中它被推入堆栈并在函数调用结束时弹出堆栈...
仍应将未命名的对象推入堆栈并保留在堆栈中,直到块结束,从而在预期时将其从堆栈中弹出。在单个语句中构造和销毁对象是没有意义的。我想看一个实际有用的单个实例/案例。如果它在块的持续时间内没有停留在范围内,那么它肯定是一个错误,并且至少应该产生警告。