【问题标题】:How does return by rvalue reference work?右值引用返回如何工作?
【发布时间】:2013-04-28 14:00:20
【问题描述】:

就在我以为我有点理解右值引用的时候,我遇到了这个问题。代码可能不必要地长,但想法很简单。有一个 main() 函数和 returnRValueRef() 函数。

#include <iostream>

#define NV(x) "[" << #x << "=" << (x) << "]"
#define log(x) cout << __FILE__ << ":" << __LINE__ << " " << x << endl

using namespace std;

class AClass {
 public:
  int a_;

  AClass() : a_(0) {
    log("inside default constructor");
  }
  AClass(int aa) : a_(aa) {
    log("inside constructor");
  }
  int getInt() const {
    return a_;
  }
  void setInt(int a) {
    a_ = a;
  }

  AClass(AClass const & other) : a_(other.a_) {
    log("inside copy constructor");
  }

  AClass & operator=(AClass const & rhs) {
    log("inside assignment operator" << "left value" << NV(a_) << "right value" << NV(rhs.a_));
    a_ = rhs.a_;
    return *this;
  }

  AClass & operator=(AClass && rhs) {
    log("inside assignment operator (rvalue ref)" << "left" << NV(a_) << "right" << NV(rhs.a_));
    a_ = rhs.a_;
    return *this;
  }
};

AClass && returnRValueRef() {
  AClass a1(4);
  return move(a1);
}

int main() {
  AClass a;
  a = returnRValueRef();
}

好的,我希望这段代码首先打印“默认构造函数内部”(对于 a),然后是“内部构造函数”(对于 a1),然后是 rhs.a_ = 4 的赋值运算符消息。但是输出是

testcpp/return_rvalue_ref.cpp:14 inside default constructor
testcpp/return_rvalue_ref.cpp:17 inside constructor
testcpp/return_rvalue_ref.cpp:39 inside assignment operator (rvalue ref)left[a_=0]right[rhs.a_=0]

谁能解释为什么输出中的最后一行打印right[rhs.a_=0] 而不是right[rhs.a_=4]?我认为 move() 只是将左值变成右值而不改变其内容。但我显然错过了一些东西。

非常感谢您的帮助。 :-)

编辑:我想我知道会发生什么。可能是函数returnRValueRef() 中的a1 的析构函数在超出范围时被调用(即使它变成了右值),之后a1 的内存位置(或它的右值引用)包含未定义的东西!不确定这是否正在发生,但似乎是合理的。

【问题讨论】:

    标签: c++11 rvalue-reference


    【解决方案1】:

    右值引用仍然是引用。在您的情况下,您正在引用已被破坏的局部变量。因此,访问成员是未定义的行为。您要做的是返回对象:

    AClass returnRValueRef() {
      AClass a1(4);
      return move(a1);
    }
    

    但是,移动会使用局部变量自动发生,因此您实际上只需要这样做:

    AClass returnRValueRef() {
      AClass a1(4);
      return a1;
    }
    

    【讨论】:

    • 感谢您的评论。在您添加评论时,我还编辑了问题,并且您所说的似乎是问题所在。谢谢。 (对不起,我不能赞成你的答案,太少了。)
    • 有没有右值引用返回有用的例子?好像没有? :(
    猜你喜欢
    • 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
    相关资源
    最近更新 更多