是否可以更改临时对象并将其作为参数传递?
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--返回一些引用,编译器看不到这个引用和我们创建的临时之间的任何关系。
答案 0 :(得分:4)
Temporaries总是活在完整表达式的生命周期中,无论如何它们都是在这个表达式中创建的。因此,在表达式语句 func_val(--getfoo());
中,getfoo()
表达式返回的临时值的生存期不需要任何扩展名。该声明直到func_val()
返回后才结束。
答案 1 :(得分:3)
func_val(--getfoo()); // #1 OK?
是的,好的。 operator--
是一个成员函数,它被调用,并返回自身(以及引用自身的左值)。然后将该对象复制到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()
返回T*
(允许)的情况。您不能修改非类型的rvalues,因此在这种情况下,这将是不正确的。
func_ref(--getfoo());
是的,好的。参数在#1
中进行求值,但是生成的左值直接传递,并且const引用绑定到它。在这个意义上它等于#3
(除了减量副作用)。
const Foo & xref = --getfoo();
标准措辞并不完全清楚。它肯定只是为了延长尚未绑定到引用的对象的生命周期。但在我们的例子中,--getfoo()
产生一个左值,引用一个先前绑定到引用的临时对象。可能值得向委员会提交缺陷报告(我可能也错过了要求临时对象不受限制参考的措辞)。
在任何情况下,预期的行为都是在初始化getfoo()
时破坏xref
产生的临时行为,因此xref
将成为悬空参考。
问题是operator_返回一些引用,编译器没有看到这个引用和我们创建的临时之间的任何关系。
完全(但仅适用于xref
的初始化,这将会发疯。在所有其他情况下,您想要的(或我认为您想要的)行为已实现。