3

是否可以更改临时对象并将其作为参数传递?

struct Foo {    
   Foo& ref() { return *this; }
   Foo& operator--() { /*do something*/; return *this; }
   // another members
};
Foo getfoo() { return Foo(); } // return Foo() for example or something else
void func_val(Foo x) {}
void func_ref(const Foo & x) {}

int main() {
   func_val(--getfoo());     // #1 OK?
   func_ref(getfoo());       // #2 OK?
   func_ref(getfoo().ref()); // #3 OK?
   // the following line is a real example 
   //    using --vector.end() instead of --getfoo()
   func_ref(--getfoo());     // #4 OK? 

   const Foo & xref = --getfoo(); //  Does const extend the lifetime ?
   func_ref(xref);     // #5 OK? 
   func_val(xref);     // #6 OK? 

}

众所周知,将临时对象分配给 const 引用会延长该临时对象的生命周期。那么我的代码的#4 和#5 行呢?引用 x 在函数 func_ref 中是否始终有效?问题是 operator-- 返回一些引用,编译器看不到这个引用和我们创建的临时值之间的任何关系。

4

2 回答 2

4

无论如何,临时对象总是在它们被创建的完整表达式的整个生命周期中存在。因此,在表达式 statement func_val(--getfoo());中,表达式返回的临时变量的生命周期getfoo()不需要任何扩展。声明直到 afterfunc_val()返回才结束。

于 2009-10-15T11:21:42.663 回答
3
func_val(--getfoo());     // #1 OK?

好的。Theoperator--是一个成员函数,它被调用并返回自身(并且左值引用自身)。然后将该对象复制到 的参数中func_val。请注意,不允许应用返回值优化,因为创建的临时对象getfoo()之前已绑定到引用。

func_ref(getfoo());       // #2 OK?

好的。该调用getfoo()返回一个绑定到 const 引用的临时值。需要一个复制构造函数,但调用它可能会被实现优化。临时持续到包含调用的完整表达式结束func_ref(此处为整个表达式语句)。

func_ref(getfoo().ref());

好的。不需要复制构造函数,因为我们将 const 引用绑定到不是临时的,而是绑定到表示对象本身的左值。

// the following line is a real example 
//    using --vector.end() instead of --getfoo()

这不是工作所必需的。想一想vector.end()返回 a T*(允许)的情况。你不能修改非类类型的右值,所以在这种情况下,这将是不正确的。

func_ref(--getfoo()); 

好的。参数被评估为 in #1,但结果左值被直接传递并且 const 引用被绑定到它。从这个意义上说,它等于#3(减量副作用除外)。

const Foo & xref = --getfoo();

标准的措辞并不完全清楚。它肯定只打算延长尚未绑定到引用的对象的生命周期。但是在我们的例子中,--getfoo()产生一个左值,它指向一个之前绑定到一个引用的临时对象。向委员会提交一份缺陷报告可能是值得的(我也可能遗漏了要求临时对象尚未绑定到引用的措辞)。

在任何情况下,预期的行为是破坏getfoo()初始化结束时产生的临时xref,因此xref将成为悬空引用。

问题是 operator-- 返回一些引用,编译器看不到这个引用和我们创建的临时值之间的任何关系。

完全正确(但仅适用于xref会发疯的初始化。在所有其他情况下,您想要的预期行为(或我相信您想要的行为)都已实现)。

于 2009-10-15T11:40:05.603 回答