[英]std::reference_wrapper around *this
我有一个场景,我需要将一个可以被*this
链接的函数转换为返回std::optional<std::reference_wrapper<T>>
而不是T&
(原因超出了这个问题的范围)。 我之所以使用std::reference_wrapper
是因为std::optional
不能引用,至少在C ++ 11中不行。 但是,这不起作用,因为我似乎遇到了终身问题。 这是一个最小的例子:
#include <iostream>
#include <functional>
struct test {
std::reference_wrapper<test> foo() {
val = 42;
return *this;
}
test& foo2() {
val = 50;
return *this;
}
int val;
};
void bar(test t) {
std::cout << std::move(t).val << "\n";
}
int main()
{
auto f = test().foo();
bar(f);
auto g = test().foo2();
bar(g);
}
这输出0 50
而不是预期的42 50
。 如果我把它分成两个陈述:
auto f = test();
auto f2 = f.foo();
bar(f2);
它按预期工作。 使用调试器,我发现编译器正在优化某些表达式并且val
初始化,这使我认为我的代码中有未定义的行为。
我有未定义的行为吗? 如果是这样,我该如何避免呢?
我有未定义的行为吗?
是。 auto
从用于初始化它的表达式中推断出对象的类型。 并使用std::reference_wrapper<test>
类型的表达式来初始化f
。 f
初始化后临时test()
消失,因此f
立即悬空。
你可以像你一样拆分声明,或者使用std::references_wrappers
的get成员函数:
auto f = test().foo().get();
无论哪种方式, std::reference_wrapper<test>
都不是C ++支持的所有上下文中的引用替换。 代理对象永远不会。
我有未定义的行为吗?
是。 看一下auto f = test().foo();
。 f
是std::reference_wrapper<test>
,它引用的test
实例是test()
。 test()
的生命周期就在这一行的末尾结束,最后你会得到一个悬空参考。 对于auto g = test().foo2();
,情况并非如此auto g = test().foo2();
因为它复制了返回值(感谢@StoryTeller帮助我这里)。
我怎么在这里避免它?
您需要从std::reference_wrapper
部分拆除生命周期管理。 这将有效:
test t;
auto f = t.foo();
// Do stuff with f until this scope ends.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.