【问题标题】: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?我之前尝试过,但遇到了一堆不受支持的软件包。

非常感谢。

【问题讨论】:

标签: c++ gcc c++11 reference rvalue


【解决方案1】:

从函数返回右值引用很少有意义(std::move 例外),因为引用可能绑定到临时对象或堆栈上的对象,就像你的情况一样,当你返回它时,对象就消失了.

编辑:

Data && foo () {
 Data d;
 return std :: move (d);
}

d 在超出范围时被销毁,因此您将返回悬空引用。

【讨论】:

  • 作为后续,为了在这里利用右值引用,只需让函数按值返回。编译器将自动使用新的移动构造函数将数据移出而不是复制。
  • @templatetypedef -- 按值返回是对的,除了编译器会在诉诸移动对象之前尝试省略副本。
【解决方案2】:

您不返回右值引用,而是返回一个值,然后调用者将其作为右值作为引用。你应该只有Data foo(),而不是Data&amp;&amp; foo()。这些作品中的任何一个都纯属巧合,因为它是未定义的行为。

【讨论】:

    【解决方案3】:

    您不能期望将&amp;&amp; 返回到本地对象有什么好处,就像返回一个常规引用​​/指向本地对象的指针一样。

    您应该按值返回。在 C++03 下,允许编译器优化对复制构造函数的调用。在 C++0x 中,这意味着(如果无法优化复制 - 例如编译器在从不同分支返回不同对象时不管理它)将调用移动构造函数而不是复制构造函数(如果可用)从函数中获取值。

    据我所知,移动语义应该在安全的地方自动启动,而右值引用参数类型允许您确定参数是否是右值(您可以显式移动的东西)。

    【讨论】:

      猜你喜欢
      • 2018-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多