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

发布于 2024-08-08 01:34:59 字数 886 浏览 5 评论 0原文

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

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

笑看君怀她人 2024-08-15 01:34:59

临时对象总是在创建它们的完整表达式的生命周期内存在。因此,在表达式语句中,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 the getfoo() expression doesn't need any extension. The statement doesn't end until after func_val() had returned.

东北女汉子 2024-08-15 01:34:59
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* (允许)的情况。不允许修改非类类型的右值,因此在这种情况下,这将是格式错误的。

func_ref(--getfoo()); 

是的,好的。参数的计算方式与 #1 相同,但生成的左值会直接传递,并且 const 引用会绑定到它。从这个意义上来说,它等于#3(除了递减副作用)。

const Foo & xref = --getfoo();

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

无论如何,预期的行为是在初始化 xref 结束时破坏 getfoo() 产生的临时结果,因此 xref 将变为悬空参考。

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

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

func_val(--getfoo());     // #1 OK?

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 of func_val. Notice that return value optimization is not allowed to apply, since the temporary created by getfoo() was previously bound to a reference.

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

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 to func_ref (the whole expression statement here).

func_ref(getfoo().ref());

Yes, OK. No copy constructor required, as we bind the const reference not to a temporary but to the lvalue representing the object itself.

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

That is not required to work. Think of a situation where vector.end() returns a T* (allowed). You are not allowed to modify rvalues of non-class type, so in that case, this would be ill-formed.

func_ref(--getfoo()); 

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).

const Foo & xref = --getfoo();

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 initializing xref, so xref will become a dangling reference.

The thing is that operator-- returns some reference and the compiler does not see any relation between this reference and the temporary we created.

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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文