是否可以更改临时对象并将其作为参数传递?
是否可以更改临时对象并将其作为参数传递?
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-- 返回一些引用,而编译器看不到该引用与我们创建的临时引用之间有任何关系。
Is it possible to change the temporary object and to pass it as an argument?
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?
}
It is known that assigning a temporary object to the const reference extends the lifetime of this temporary object. And what about #4 and #5 lines of my code?
Is it true that reference x is always valid in the function func_ref?
The thing is that operator-- returns some reference and the compiler does not see any relation between this reference and the temporary we created.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
临时对象总是在创建它们的完整表达式的生命周期内存在。因此,在表达式语句中,
func_val(--getfoo());
中,getfoo()
表达式返回的临时变量的生命周期并不不需要任何扩展。该语句直到func_val()
返回后才结束。Temporaries always live for the lifetime of the full expression in which they're created anyway. Hence, in the expression statement
func_val(--getfoo());
, the lifetime of the temporary returned by thegetfoo()
expression doesn't need any extension. The statement doesn't end until afterfunc_val()
had returned.是的,好的。
operator--
是一个成员函数,它被调用并返回自身(以及引用自身的左值)。然后该对象被复制到func_val
的参数中。请注意,不允许应用返回值优化,因为由getfoo()
创建的临时对象之前已绑定到引用。是的,好的。调用
getfoo()
返回一个绑定到 const 引用的临时值。复制构造函数是必需的,但它的调用可能会被实现优化。临时值持续存在,直到包含对 func_ref 的调用的完整表达式结束(此处为整个表达式语句)。是的,好的。不需要复制构造函数,因为我们将 const 引用绑定到表示对象本身的左值而不是临时引用。
这不是工作所必需的。考虑一下
vector.end()
返回T*
(允许)的情况。不允许修改非类类型的右值,因此在这种情况下,这将是格式错误的。是的,好的。参数的计算方式与
#1
相同,但生成的左值会直接传递,并且 const 引用会绑定到它。从这个意义上来说,它等于#3
(除了递减副作用)。标准的措辞并不完全清楚。它肯定只打算延长尚未绑定到引用的对象的生命周期。但在我们的例子中,
--getfoo()
生成一个左值,该左值引用先前绑定到引用的临时对象。可能值得向委员会提交一份缺陷报告(我也可能错过了要求临时对象不受引用限制的措辞)。无论如何,预期的行为是在初始化
xref
结束时破坏getfoo()
产生的临时结果,因此xref
将变为悬空参考。完全正确(但仅适用于
xref
的初始化,这会变得疯狂。在所有其他情况下,您想要的预期行为(或我相信您想要的)都已实现)。Yes, OK. The
operator--
is a member-function, which is called, and which returns itself (and lvalue referring to itself). The object is then copied into the parameter offunc_val
. Notice that return value optimization is not allowed to apply, since the temporary created bygetfoo()
was previously bound to a reference.Yes, OK. The call
getfoo()
returns a temporary which is bound to the const reference. A copy constructor is required, but the call it it may be optimized out by the implementation. The temporary persists until the end of the full-expression containing the call tofunc_ref
(the whole expression statement here).Yes, OK. No copy constructor required, as we bind the const reference not to a temporary but to the lvalue representing the object itself.
That is not required to work. Think of a situation where
vector.end()
returns aT*
(allowed). You are not allowed to modify rvalues of non-class type, so in that case, this would be ill-formed.Yes, OK. The argument is evaluated as in
#1
, but the resulting lvalue is directly passed and the const reference is bound to it. In this sense it's equal to#3
(except for the decrement side effect).The Standard wording is not entirely clear. It surely intends to only extend lifetime of objects not yet bound to a reference. But in our case,
--getfoo()
yields an lvalue refering to a temporary object which was previously bound to a reference. It may be worth submitting a defect report to the committee (i may also have missed wording that requires the temporary object to not be bounded to a reference yet).In any case, the intended behavior is to destruct the temporary that results from
getfoo()
at the end of initializingxref
, soxref
will become a dangling reference.Exactly (but applies only to the initialization of
xref
which will go mad. In all other cases, the intended behavior you want (or what i believe you want) is achieved).