深返回时右值引用中断
Posted
技术标签:
【中文标题】深返回时右值引用中断【英文标题】:rvalue references break when deep-returning 【发布时间】:2011-01-07 20:22:19 【问题描述】:我在从超过 1 的深度传递返回的右值引用时遇到了问题。
struct Data
std :: vector <int> data;
Data ()
data .push_back (1);
;
Data (Data && d)
: data (std :: move (d .data))
;
Data && foo ()
Data d;
return std :: move (d);
Data && bar ()
return std :: move (foo ()); // Crashes in autogenerated code
Data && baz ()
return foo (); // Crashes in Data move constructor.
Data && bop ()
Data d = foo ();
return std :: move (d); // Crashes in autogenerated code.
int main ()
Data d_foo = foo (); // This is fine.
Data d_bar = bar (); // Crash.
Data d_bar = baz (); // Crash.
Data d_bop = bop (); // Crash.
我认为 std::vector 正在被双重释放。我正在使用 g++ (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5
上面的代码对你有用吗?我做错了什么还是库或编译器中存在错误?
如果(天堂原谅)它是编译器(gcc 中还有其他已知的 C++0x 错误),有人可以告诉我是否有一种安全的方式来升级或修补 ubuntu 上的 gcc?我之前尝试过,但遇到了一堆不受支持的软件包。
非常感谢。
【问题讨论】:
你应该关注this video 的右值引用。 【参考方案1】:从函数返回右值引用很少有意义(std::move 例外),因为引用可能绑定到临时对象或堆栈上的对象,就像你的情况一样,当你返回它时,对象就消失了.
编辑:
Data && foo ()
Data d;
return std :: move (d);
d
在超出范围时被销毁,因此您将返回悬空引用。
【讨论】:
作为后续,为了在这里利用右值引用,只需让函数按值返回。编译器将自动使用新的移动构造函数将数据移出而不是复制。 @templatetypedef -- 按值返回是对的,除了编译器会在诉诸移动对象之前尝试省略副本。【参考方案2】:您不返回右值引用,而是返回一个值,然后调用者将其作为右值作为引用。你应该只有Data foo()
,而不是Data&& foo()
。这些作品中的任何一个都纯属巧合,因为它是未定义的行为。
【讨论】:
【参考方案3】:您不能期望将&&
返回到本地对象有什么好处,就像返回一个常规引用/指向本地对象的指针一样。
您应该按值返回。在 C++03 下,允许编译器优化对复制构造函数的调用。在 C++0x 中,这意味着(如果无法优化复制 - 例如编译器在从不同分支返回不同对象时不管理它)将调用移动构造函数而不是复制构造函数(如果可用)从函数中获取值。
据我所知,移动语义应该在安全的地方自动启动,而右值引用参数类型允许您确定参数是否是右值(您可以显式移动的东西)。
【讨论】:
以上是关于深返回时右值引用中断的主要内容,如果未能解决你的问题,请参考以下文章